home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / prog_gen / wdj0796.zip / SDKANN.ZIP / SDKANN.TXT < prev   
Text File  |  1996-05-08  |  91KB  |  2,799 lines

  1. Please send us your annotations!  Just email them to
  2. 70302.2566@compuserve.com and indicate the topic and
  3. the help file that your annotation refers to. Help
  4. us build the SDK annotation database!
  5.  
  6. 5/8/96 NOTE:
  7.  
  8. The AnnTater utility mentioned below has been mutated
  9. to work with the InfoViewer that is integrated in
  10. the Visual C++ IDE. Instead of running anntater.exe,
  11. run mstater.exe if you want to annotate the IDE
  12. InfoViewer (rather than any .hlp files you may have).
  13. Let me know if you have problems.
  14.  
  15.  
  16. 12/1/95 NOTE:
  17.  
  18. The WDJ annotation package now includes anntater.exe. 
  19. AnnTater contains all of our annotations and you can use it
  20. to automatically place our annotations in your help file. 
  21. Although I've tried to test this software in a variety of
  22. situations, USE IT AT YOUR OWN RISK.  If you have
  23. annotations of your own, you may want to back up your .ann
  24. file before running AnnTater. To use AnnTater, follow
  25. these steps. If you don't have annotations of your own, the
  26. easiest route is to delete your .ann file each time you run
  27. anntater.exe on a new installment of our annotations.
  28.  
  29. 1) invoke anntater.exe
  30. 2) select a type of help file (Windows 3.1 API or Win32 API)
  31. 3) if necessary, press the Locate button to specify the
  32.    path where this helpfile exists
  33. 4) select one or more annotations that you want to install
  34. 5) press the Copy button
  35. 6) press Done
  36.  
  37. Note that the program displays a checkmark beside
  38. each annotation that it believes it has successfully
  39. installed during the current session.
  40.  
  41.  
  42. ----------
  43.  
  44. This is the Windows Developer's Journal SDK Annotation File, a
  45. growing collection of useful annotations for the standard online Windows
  46. API help file, win31wh.hlp, which is included with every Windows C++
  47. compiler.  You can either cut and paste these annotations into your own
  48. SDK help file (use ALT-E-A to create a help topic annotation), or you
  49. can use anntater.exe to install them automatically for you.
  50.  
  51. If you have a useful annotation you would like to submit to our
  52. collection, send it to:
  53.  
  54.     70302.2566@compuserve.com
  55.  
  56. If we use your annotation, you will be listed as the
  57. contributor.  Our thanks to the dozens of readers whose
  58. contributions help us continue to build this database of
  59. useful information for the Windows programming community.
  60.  
  61.  
  62.  
  63.     Windows Developer's Journal
  64.  
  65.     "The Magazine for Windows Developers"
  66.  
  67. Windows Developer's Journal is the monthly publication for
  68. advanced Windows programmers.  We cover a variety of topics
  69. such as Windows 95 programming, NT programming device
  70. drivers, undocumented functions, compiler bugs, operating
  71. system bugs, graphics, MFC, multimedia, communications, and
  72. so on -- usually in the form of reusable code that you can
  73. use immediately (most of our code has been compiled with
  74. both Borland and Microsoft C/C++ compilers).  In addition,
  75. each month contains regular features like these:
  76.  
  77. * SDK Annotations
  78.     (they appear in the magazine before they appear in this file)
  79. * Bug++ of the Month
  80.     (nasty bugs in popular C++ compilers)
  81. * Tech Tips
  82.     (user-submitted tips and techniques)
  83. * Books in Brief
  84.     (quick looks at recent books)
  85. * Understanding NT
  86.     (covers NT-specific programming issues)
  87.  
  88. and more.  WDJ costs $34.99/year in the US, $45/year Canada/Mexico, or
  89. $64/year overseas.  To order a subscription, contact
  90.  
  91.     Miller Freeman
  92.     P.O. Box 56565
  93.     Boulder, CO 80322-6565
  94.     (800) 365-1425
  95.     (303) 678-0439
  96.     wdsub@rdpub.com
  97.  
  98. To subscribe by email or fax, include your name, address,
  99. phone number, MasterCard or Visa number, and expiration
  100. date.  From CompuServe, that email address would be
  101. something like this:
  102.  
  103.    >INTERNET:wdsub@rdpub.com
  104.  
  105.   
  106. ------------------------------------------------------------
  107.  
  108. WDJ SDK Annotation #1
  109. TYPE:       Win3.1
  110. TOPIC:      Dialog Boxes
  111. KEYWORD:    Dialog Boxes
  112.  
  113. If a listbox is the first control in a dialog's tab order
  114. and the dialog box was not created with the WS_VISIBLE
  115. style, the listbox does not correctly draw itself with the
  116. focus.
  117.  
  118. Reference: p35, March 1993 Windows/DOS Developer's Journal.
  119.  
  120. ------------------------------------------------------------
  121.  
  122. WDJ SDK Annotation #2
  123. TYPE:       Win3.1
  124. TOPIC:      Property Lists
  125. KEYWORD:    Property Lists
  126.  
  127. The oft-quoted maxim that using window properties is slower
  128. than using class or window extra bytes (via
  129. GetWindowWord()/SetWindowWord()) is totally false if you use
  130. a global atom rather than a string to name the property. 
  131. Properties were about 20% slower than window words under
  132. Windows 3.0, but under Windows 3.1 GetProp() is about 300%
  133. faster than GetWindowWord().
  134.  
  135. Reference: p 49, March 1993 Windows/DOS Developer's Journal.
  136.  
  137. ------------------------------------------------------------
  138.  
  139. WDJ SDK Annotation #3
  140. TYPE:       Win3.1
  141. TOPIC:      WM_MOUSEMOVE (2.x)
  142. KEYWORD:    WM_MOUSEMOVE
  143.  
  144. The documentation incorrectly states that the x and y
  145. arguments are in screen coordinates.  They are in client
  146. coordinates. 
  147.  
  148.  
  149. ------------------------------------------------------------
  150.  
  151. WDJ SDK Annotation #4 (revised)
  152. TYPE:       Win3.1
  153. TOPIC:      SetWindowsHookEx (3.1)
  154. KEYWORD:    SetWindowsHookEx
  155.  
  156. SetWindowsHookEx() has a bug: using it to install a
  157. task-specific hook can cause various failures.  The
  158. workaround is to pass it a module handle rather than an
  159. instance handle.  You can obtain a module handle from
  160. GetModuleHandle().  If you only have the current instance
  161. handle and not the name of the module, use the following
  162. undocumented hack under Windows 3.1:
  163.  
  164. GetModuleHandle(MAKELP(0,hInstance));
  165.  
  166. If you #include <windowsx.h>, you can instead use the macro
  167. GetInstanceModule(hInstance).  Under Windows NT, just pass a
  168. NULL to obtain the handle of the current process.  Note that
  169. the MSDN News article on this subject has the arguments to
  170. MAKELP() backwards. 
  171.  
  172.  
  173. Reference: MSDN News #1, 1993
  174. Revised by: Tom Nolan
  175.  
  176. ------------------------------------------------------------
  177.  
  178. WDJ SDK Annotation #5
  179. TYPE:       Win3.1
  180. TOPIC:      CS_BYTEALIGNWINDOW 0x2000
  181. KEYWORD:    CS_BYTEALIGNWINDOW
  182.  
  183. The documentation makes it sound like this style bit is the
  184. one you want for efficient bitblts.  In fact, most of your
  185. bitblts will be to the client area of the window, not the
  186. non-client area, so CS_BYTEALIGNCLIENT is the style bit you
  187. should set if you are concerned about bitblt operation
  188. efficiency.  Unaligned windows are slower at VGA resolution,
  189. but typically not an issue with higher resolution
  190. adapters (such as 256-color SVGA). 
  191.  
  192. Reference: p65, December 1993 Windows/DOS Developer's Journal.
  193.  
  194.  
  195. ------------------------------------------------------------
  196.  
  197. WDJ SDK Annotation #6
  198. TYPE:       Win3.1
  199. TOPIC:      CODE Module Definition Statement
  200. KEYWORD:    CODE Module Definition Statement
  201.  
  202. The documentation for the FIXED attribute is incorrect. 
  203. Under Windows 3.1, if you mark code or data segments in your
  204. .exe FIXED, the loader ignores that attribute -- the
  205. segments will be moveable.  If you mark code or data
  206. segments in your .dll FIXED, however, the loader will make
  207. them fixed and will page lock them as well.  Due to the
  208. implementation of GlobalPageLock(), that can result in your
  209. segments using up precious DOS memory, eventually preventing
  210. Windows from spawning new applications (since each new
  211. application needs at least 512 bytes of DOS memory for a
  212. task database entry).  The October 1994 Windows
  213. Developer's Journal provides code to allocate fixed memory
  214. without using up precious conventional memory. 
  215.  
  216.  
  217. ------------------------------------------------------------
  218.  
  219. WDJ SDK Annotation #7
  220. TYPE:       Win3.1
  221. TOPIC:      WS_EX_TRANSPARENT 0x00000020L
  222. KEYWORD:    WS_EX_TRANSPARENT
  223.  
  224. Note that this bit does not really create transparent
  225. windows.  If you create a window with this style, it is true
  226. that the windows below it will show through as its
  227. background.  However, if you then move your new window, it
  228. will have the same background as it did in its original
  229. position -- blotting out whatever it is covering in its new
  230. position. 
  231.  
  232. ------------------------------------------------------------
  233.  
  234. WDJ SDK Annotation #8
  235. TYPE:       Win3.1
  236. TOPIC:      WM_NCHITTEST (2.x)
  237. KEYWORD:    WM_NCHITTEST
  238.  
  239. You can process this message to allow the user to drag a
  240. window that does not have a title bar.  When you receive a
  241. WM_NCHITTEST message and the mouse is in your client area
  242. (or whatever conditions you want to start the drag), just
  243. return HTCAPTION rather than passing the message on to
  244. DefWindowProc(). 
  245.  
  246. Reference: p 37, March 1993 Windows/DOS Developer's Journal.
  247.  
  248.  
  249. ------------------------------------------------------------
  250.  
  251. WDJ SDK Annotation #9
  252. TYPE:       Win3.1
  253. TOPIC:      WM_TIMER (2.x)
  254. KEYWORD:    WM_TIMER
  255.  
  256. Although it sounds odd, you can use a WM_TIMER message as a
  257. way to kill another application, if you can obtain the
  258. handle of the main of the application you want to kill. 
  259. Create a timer callback function that does nothing but pass
  260. its first argument (window handle) to DestroyWindow().  Then
  261. use PostMessage() to post (to the other app's main window) a
  262. WM_TIMER message that points to your callback function. 
  263. Your timer callback will get executed in the context of the
  264. target application. 
  265.  
  266. Reference: p 64, September 1992 Windows/DOS Developer's Journal.
  267.  
  268.  
  269.  
  270. ------------------------------------------------------------
  271.  
  272. WDJ SDK Annotation #10
  273. TYPE:       Win3.1
  274. TOPIC:      MemoryWrite (3.1)
  275. KEYWORD:    MemoryWrite
  276.  
  277. MemoryWrite() has a bug in it: it trashes the high 16 bits
  278. of the EDI register (the 32-bit version of the DI register). 
  279. The workaround is to save the register before calling
  280. MemoryWrite() and restore it afterward. 
  281.  
  282. Reference: p. 71, April 1994 Windows/DOS Developer's Journal
  283.  
  284.  
  285.  
  286. ------------------------------------------------------------
  287.  
  288. WDJ SDK Annotation #11
  289. TYPE:       Win3.1
  290. TOPIC:      EscapeCommFunction (2.x)
  291. KEYWORD:    EscapeCommFunction
  292.  
  293. The documentation omits one potential value for the
  294. nFunction parameter, although it is defined in windows.h. 
  295. The name is GETBASEIRQ and it returns the base address of
  296. the COM port in the lower word and the IRQ setting in the
  297. high word.  If the high word is -1 the port doesn't exist;
  298. if it is 0, the comm driver does not support this escape
  299. (which is the case, for example with some kinds of enhanced
  300. serial boards). 
  301.  
  302. Submitted by: Thomas Zeisluft
  303.  
  304. ------------------------------------------------------------
  305.  
  306. WDJ SDK Annotation #12
  307. TYPE:       Win3.1
  308. TOPIC:      MessageBox (2.x)
  309. KEYWORD:    MessageBox
  310.  
  311. Do not call MessageBox() from within the LibMain() of an
  312. implicitly-linked DLL.  It will fail because the application
  313. will not yet have a message queue at that point, and
  314. MessageBox() (or anything else) cannot create its window
  315. when the message queue does not yet exist.  Once the
  316. application executes its internal startup code and calls
  317. InitApp(), then it has a message queue and can safely call
  318. functions that create windows. 
  319.  
  320. ------------------------------------------------------------
  321.  
  322. WDJ SDK Annotation #13
  323. TYPE:       Win3.1
  324. TOPIC:      LB_ADDSTRING (2.x)
  325. KEYWORD:    LB_ADDSTRING
  326.  
  327. If you are changing the contents of a listbox (for example,
  328. by adding or deleting multiple strings), you may want to
  329. minimize screen redrawing and maximize speed by disabling
  330. window redrawing during your operation.  Follow these steps:
  331.  
  332.  1) Send a WM_SETREDRAW with wParam equal to FALSE to the listbox.
  333.  2) Perform your adds or deletes.
  334.  3) Send a WM_SETREDRAW with wParam equal to TRUE to the listbox.
  335.  4) Use InvalidateRect() to force the listbox to redraw itself.
  336.  
  337. Revised by V. Ramachandran
  338.  
  339. ------------------------------------------------------------
  340.  
  341. WDJ SDK Annotation #14
  342. TYPE:       Win3.1
  343. TOPIC:      RegisterWindowMessage (2.x)
  344. KEYWORD:    RegisterWindowMessage
  345.  
  346. Do you really need to register a private window message?
  347. Probably not, if all you need is an intra-app message number
  348. that does not conflict with any Windows message numbers. 
  349. Microsoft has revised its statement about what message
  350. numbers are available for your private use.  Microsoft now
  351. guarantees that you can use message numbers 0x8000 through
  352. 0xBFFF and they will not conflict with any system messages. 
  353. They also claim the next SDK (Chicago?) will define WM_APP
  354. equal to 0x8000 in windows.h. 
  355.  
  356. Reference: Microsoft Knowledge Base article Q86835
  357.  
  358.  
  359.  
  360. ------------------------------------------------------------
  361.  
  362. WDJ SDK Annotation #15
  363. TYPE:       Win3.1
  364. TOPIC:      WM_CHAR (2.x)
  365. KEYWORD:    WM_CHAR
  366.  
  367. The documentation incorrectly claims that wParam is the
  368. virtual key code.  In fact, it is the ASCII value of the key
  369. pressed.  For example, pressing the '$' (ASCII 0x5B) key
  370. produces a wParam equal to 0x5B -- if you interpreted that
  371. as a virtual key code, you would incorrectly believe that
  372. the user had pressed VK_HOME!
  373.  
  374. Submitted by: Brent Rector
  375.  
  376. ------------------------------------------------------------
  377.  
  378. WDJ SDK Annotation #16
  379. TYPE:       Win3.1
  380. TOPIC:      WinHelp (3.0)
  381. KEYWORD:    WinHelp
  382.  
  383. The documentation says that the return value is nonzero if
  384. WinHelp() is successful.  In fact, WinHelp() only returns
  385. failure for systemic problems, like being unable to allocate
  386. global memory, or being unable to spawn winhelp.exe.  If
  387. WinHelp() successfully passes your request to winhelp.exe,
  388. it returns success, period.  So, for example, if the named
  389. help file is invalid, or you try to jump to a help topic
  390. that does not exist, or any number of other logical errors,
  391. WinHelp() still returns success. 
  392.  
  393. ------------------------------------------------------------
  394.  
  395. WDJ SDK Annotation #17
  396. TYPE:       Win3.1
  397. TOPIC:      WM_ENTERIDLE (2.x)
  398. KEYWORD:    WM_ENTERIDLE
  399.  
  400. The documentation says that this messsage gets sent to your
  401. application's "main window".  In fact, a dialog sends the
  402. WM_ENTERIDLE message to its own parent window, which may or
  403. may not happen to be your application's main window. 
  404.  
  405.  
  406. ------------------------------------------------------------
  407.  
  408. WDJ SDK Annotation #18
  409. TYPE:       Win3.1
  410. TOPIC:      OPENFILENAME (3.1)
  411. KEYWORD:    OPENFILENAME
  412.  
  413. The documentation does not completely describe the behavior
  414. when selecting multiple files.  To allow the user to select
  415. multiple files, you turn on the flag OFN_ALLOWMULTISELECT. 
  416. If you do that and call GetOpenFileName(), and if the user then
  417. selects multiple files, then GetOpenFileName() will copy (into
  418. lpstrFile) the path, followed by a space, followed by
  419. space-separated filenames.  For example, if the user
  420. selected files "fred.1" and "fred.2" from directory
  421. "c:\test", lpstrFile would then point to the following
  422. string:
  423.  
  424.     "c:\test fred.1 fred.2"
  425.  
  426. However, the documentation does not point out that if the
  427. user selects only one file, then the path is not kept
  428. separate from the filename.  Using the previous example, if
  429. the user selected only file "fred.1", then lpstrFile would
  430. point to this:
  431.  
  432.     "c:\test\fred.1"
  433.  
  434. Submitted by Julian Templeman
  435.  
  436.  
  437.  
  438. ------------------------------------------------------------
  439.  
  440. WDJ SDK Annotation #19
  441. TYPE:       Win3.1
  442. TOPIC:      CreateRoundRectRgn (3.0)
  443. KEYWORD:    CreateRoundRectRgn
  444.  
  445. This function has a bug.  It will produce a GP fault if the
  446. region rectangle is empty (either nLeftRect equals
  447. nRightRect, or nBottomRect equals nTopRect).  About the only
  448. workaround is to create a wrapper function that first checks
  449. whether the rectangle is empty. 
  450.  
  451. Reference: p67, June 1994 Windows/DOS Developer's Journal^
  452. Submitted by Chris Mason
  453.  
  454.  
  455.  
  456. ------------------------------------------------------------
  457.  
  458. WDJ SDK Annotation #20
  459. TYPE:       Win3.1
  460. TOPIC:      EnableMenuItem (2.x)
  461. KEYWORD:    EnableMenuItem
  462.  
  463. When you are making changes to a window menu, the menu bar
  464. is not immediately updated.  To force those changes (such as
  465. enabling/disabling menu items) to be visible right away,
  466. make sure you call DrawMenuBar(). 
  467.  
  468. ------------------------------------------------------------
  469.  
  470. WDJ SDK Annotation #21
  471. TYPE:       Win3.1
  472. TOPIC:      DrawText (2.x)
  473. KEYWORD:    DrawText
  474.  
  475. DrawText() has an off-by-one error that can result in a GP
  476. fault.  The bug is evoked when you use pass an explicit
  477. string length instead of NULL-terminating the text string. 
  478. The bug is not evoked if you use the DT_NOPREFIX flag, or if
  479. you NULL-terminate the text string (the easiest workaround). 
  480.  
  481. Reference: p53, August 1994 Windows/DOS Developer's Journal
  482.  
  483. ------------------------------------------------------------
  484.  
  485. WDJ SDK Annotation #22
  486. TYPE:       Win3.1
  487. TOPIC:      WM_MEASUREITEM (3.0)
  488. KEYWORD:    WM_MEASUREITEM
  489.  
  490. Windows supports owner-draw menus, but only popup owner-draw
  491. menus work correctly.  If you try to create an owner-draw
  492. menubar for a window, Windows will not send you the
  493. WM_MEASUREITEM message as it should. 
  494.  
  495. Reference: Microsoft Knowledge Base article Q69969
  496.  
  497. ------------------------------------------------------------
  498.  
  499. WDJ SDK Annotation #23
  500. TYPE:       Win3.1
  501. TOPIC:      WINDOWPOS (3.1)
  502. KEYWORD:    WINDOWPOS
  503.  
  504. The documentation says that y is "the position of the right
  505. edge of the window".  It is, of course, the position of the
  506. top edge of the window. 
  507.  
  508.  
  509. ------------------------------------------------------------
  510.  
  511. WDJ SDK Annotation #24
  512. TYPE:       Win3.1
  513. TOPIC:      Shell Dynamic-Data Exchange Interface Overview (3.1)
  514. KEYWORD:    Shell Dynamic-Data Exchange Interface Overview
  515.  
  516. The documentation says you can use DDE to get a list of
  517. Program Manager groups by "issuing a request for the Group
  518. item." In fact, that is not the correct item name -- you
  519. must use 'Groups', not 'Group'. 
  520.  
  521.  
  522.  
  523. ------------------------------------------------------------
  524.  
  525. WDJ SDK Annotation #25
  526. TYPE:       Win3.1
  527. TOPIC:      TrackPopupMenu (3.0)
  528. KEYWORD:    TrackPopupMenu
  529.  
  530. The documentation incorrectly states that you can pass the
  531. TPM_RIGHTBUTTON flag if you want the menu to respond to the
  532. right (secondary) mouse button instead of the left (primary)
  533. mouse button.  In fact, passing TPM_RIGHTBUTTON causes the
  534. menu to respond to the right mouse button as well as the
  535. left.  There is apparently no combination of bits that cause
  536. the menu to respond only to the right mouse button. 
  537.  
  538.  
  539. ------------------------------------------------------------
  540.  
  541. WDJ SDK Annotation #26
  542. TYPE:       Win3.1
  543. TOPIC:      SetDlgItemText (2.x)
  544. KEYWORD:    SetDlgItemText
  545.  
  546. There is a bug in Windows that keeps SetWindowText() and
  547. SetDlgItemText() from working correctly when applied to an
  548. edit control owned by another application.  Rather than
  549. sending a WM_SETTEXT to the edit control as they should,
  550. these functions directly tinker with the target control's
  551. internal window structure to change its title.  The bug,
  552. then, is twofold:
  553.  
  554.  a) The target window is never notified that it
  555.     needs to repaint.
  556.  b) An edit control ignores its title, so changing
  557.     its title does not affect the text it contains.
  558.  
  559. The workaround is to use SendMessage() or PostMessage() to
  560. deliver a WM_SETTEXT to the target window.  If you use
  561. PostMessage(), make sure you pass a string pointer that is
  562. somehow guaranteed to still be valid whenever the target
  563. application gets around to fetching and processing the
  564. message. 
  565.  
  566. Reference: p. 71, September 1993 Windows/DOS Developer's Journal
  567.  
  568.  
  569. ------------------------------------------------------------
  570.  
  571. WDJ SDK Annotation #27
  572. TYPE:       Win3.1
  573. TOPIC:      GetMenuItemID (2.x)
  574. KEYWORD:    GetMenuItemID
  575.  
  576. The documentation says that this function returns 0 if the
  577. specified menu item is a separator.  In fact, although the
  578. resource compiler implicitly assigns separators an ID of 0,
  579. you can assign them any 16-bit ID you like (with
  580. ModifyMenu(), InsertMenu(), etc.) and this function will
  581. return the correct ID, not just zero. 
  582.  
  583.  
  584. ------------------------------------------------------------
  585.  
  586. WDJ SDK Annotation #28
  587. TYPE:       Win3.1
  588. TOPIC:      GetMetaFile (2.x)
  589. KEYWORD:    GetMetaFile
  590.  
  591. Most programs that write a "Windows metafile" to disk use a
  592. newer file format that this function does not understand. 
  593. Most programs read and write "placeable" metafiles, a
  594. metafile with a 22-byte header that contains a minimum
  595. bounding rectangle for the figure.  If you want to read in a
  596. metafile that may have been written by another application,
  597. you should open the file yourself and check the header to
  598. see if it is a placeable metafile.  See the SDK
  599. documentation for a description of "placeable Windows
  600. metafiles". 
  601.  
  602. Reference: p. 43, November 1994 Windows/DOS Developer's Journal
  603.  
  604.  
  605. ------------------------------------------------------------
  606.  
  607. WDJ SDK Annotation #29
  608. TYPE:       Win3.1
  609. TOPIC:      WritePrivateProfileString (3.0)
  610. KEYWORD:    WritePrivateProfileString
  611.  
  612. The documentation for WritePrivateProfileString() and the
  613. prototypes in windows.h, indicate that all strings passed in
  614. are LPCSTR (32-bit pointer to unmodifiable character
  615. string).  However, sometimes this function writes on your
  616. input string anyway! For one example, if you pass in the
  617. string
  618.  
  619. "Hello World     "
  620.  
  621. the function will remove the trailing spaces by writing a
  622. NULL byte after the 'd'.  If you were passing in a constant
  623. string that resided in a code segment, this aberrant
  624. behavior could result in a GP fault.  This function
  625. absolutely should not modify a string declared as LPCSTR,
  626. but since it does, beware!
  627.  
  628. Submitted by Charles Leamon
  629.  
  630. ------------------------------------------------------------
  631.  
  632. WDJ SDK Annotation #30
  633. TYPE:       Win3.1
  634. TOPIC:      GetMenuState (2.x)
  635. KEYWORD:    GetMenuState
  636.  
  637. In addition to the bits noted in the documentation, this
  638. function also correctly returns MF_POPUP for a submenu. 
  639. Oddly, if you located the popup by position, the
  640. MF_BYPOSITION flag will also be set in the returned flags,
  641. although it is not on when used to locate normal menu items. 
  642. Note that some of these flags equate to zero, so you cannot
  643. just AND them with the returned flags to see if they are on. 
  644. Here are the flags that equate to zero, along with the
  645. expression you can use to infer their presence:
  646.  
  647.  Zero Flag               Expression to test for flag
  648.  ==============   =================================
  649.  MF_ENABLED       !(Flag&~(MF_DISABLED|MF_GRAYED)) 
  650.  MF_UNCHECKED     !(Flag&~MF_CHECKED)              
  651.  MF_STRING        !(Flag&~(MF_BITMAP|MF_OWNERDRAW))
  652.  
  653.  
  654. ------------------------------------------------------------
  655.  
  656. WDJ SDK Annotation #31
  657. TYPE:       Win3.1
  658. TOPIC:      GetWindowPlacement (3.1)
  659. KEYWORD:    GetWindowPlacement
  660.  
  661. From the documentation, you might think the following code
  662. would work:
  663.  
  664.  WINDOWPLACEMENT Info;
  665.  GetWindowPlacement(hWnd, &Info);
  666.  
  667. In fact, it won't.  You must remember to initialize the
  668. "length" field of the structure before calling this
  669. function.  The following code works:
  670.  
  671.  WINDOWPLACEMENT Info;
  672.  Info.length  = sizeof(Info);
  673.  GetWindowPlacement(hWnd, &Info);
  674.  
  675. Submitted by Pete Davis
  676.  
  677.  
  678.  
  679. ------------------------------------------------------------
  680.  
  681. WDJ SDK Annotation #32
  682. TYPE:       Win3.1
  683. TOPIC:      CreateCompatibleBitmap (2.x)
  684. KEYWORD:    CreateCompatibleBitmap
  685.  
  686. The description of height and width parameters states that
  687. these values are in bits, when actually they are in pixels. 
  688.  
  689. Submitted by Charles Leamon
  690.  
  691.  
  692. ------------------------------------------------------------
  693.  
  694. WDJ SDK Annotation #33
  695. TYPE:       Win3.1
  696. TOPIC:      LoadCursor (2.x)
  697. KEYWORD:    LoadCursor
  698.  
  699. The documentation says that you should call DestroyCursor()
  700. for cursors loaded via LoadCursor().  That is wrong -- you
  701. should only call DestroyCursor() for cursors created with
  702. CreateCursor(). 
  703.  
  704. Submitted by Charles Leamon^
  705. Reference: Microsoft Knowledge Base article Q84779
  706.  
  707.  
  708. ------------------------------------------------------------
  709.  
  710. WDJ SDK Annotation #34
  711. TYPE:       Win3.1
  712. TOPIC:      lstrcpyn (3.1)
  713. KEYWORD:    lstrcpyn
  714.  
  715. The documentation for lstrcpyn() states that the last
  716. parameter (cChars) is the number of characters to be copied,
  717. when in fact the number of characters will be cChars-1. 
  718. That's convenient, but it's not what it says and it's
  719. inconsistent with the standard ANSI C run-time function
  720. strncpy(), which does copy the specified count.  In other
  721. words, unlike strncpy(), this function always
  722. NULL-terminates the destination string. 
  723.  
  724. Submitted by Charles Leamon
  725.  
  726.  
  727. ------------------------------------------------------------
  728.  
  729. (Note, this annotation proved to be incorrect and therefore does not
  730. appear in the .ann files anymore.)
  731.  
  732. WDJ SDK Annotation #35
  733. TYPE:       Win3.1
  734. TOPIC:      ExitWindows (3.0)
  735. KEYWORD:    ExitWindows
  736.  
  737. In order for the EW_RESTARTWINDOWS feature to work,
  738. ExitWindows() apparently must be able to locate WIN.COM. 
  739. Otherwise, calling ExitWindows() just exits Windows without
  740. restarting.  ExitWindows() doesn't seem to be very smart
  741. about finding WIN.COM; having \WINDOWS on the DOS path
  742. doesn't seem to do it, and it apparently doesn't search for
  743. \WINDOWS on its own.  The application using ExitWindows() in
  744. this fashion should therefore either reside in the \WINDOWS
  745. directory, or should change its current directory into the
  746. \WINDOWS directory before calling ExitWindows() with
  747. EW_RESTARTWINDOWS.  Note that the user may have installed
  748. Windows in a directory other than \WINDOWS, so you may want
  749. to call GetWindowsDirectory() first. 
  750.  
  751. Submitted by Stephen Posey
  752.  
  753.  
  754. ------------------------------------------------------------
  755.  
  756. WDJ SDK Annotation #36
  757. TYPE:       Win3.1
  758. TOPIC:      ExitWindows (3.0)
  759. KEYWORD:    ExitWindows
  760.  
  761. The documentation is incomplete.  To just terminate Windows
  762. and return control to DOS, pass a zero in the dwReturnCode
  763. parameter. 
  764.  
  765. Submitted by Charles Leamon^
  766. Reference: Microsoft Knowledge Base article Q100359
  767.  
  768.  
  769. ------------------------------------------------------------
  770.  
  771. WDJ SDK Annotation #37
  772. TYPE:       Win3.1
  773. TOPIC:      OpenFile (2.x)
  774. KEYWORD:    OpenFile
  775.  
  776. WDJ SDK Annotation #37
  777.  
  778. The descriptions for OF_CANCEL and OF_PROMPT are incorrect. 
  779. OF_CANCEL does not add a cancel button to the 'File not
  780. found' (OF_PROMPT) dialog.  Even if it did, how would the
  781. caller know the user pressed the cancel button (only one
  782. error return is defined for OpenFile())? The OF_PROMPT
  783. dialog does not prompt the user to insert a diskette into
  784. drive A:
  785.  
  786. Submitted by Charles Leamon
  787.  
  788.  
  789.  
  790. ------------------------------------------------------------
  791.  
  792. WDJ SDK Annotation #38
  793. TYPE:       Win3.1
  794. TOPIC:      WM_NCHITTEST (2.x)
  795. KEYWORD:    WM_NCHITTEST
  796.  
  797. The documentation claims that this message is sent to the
  798. window that used SetCapture() to capture mouse input.  That
  799. is totally false.  The window whose handle is passed to
  800. SetCapture() will never receive any WM_NCHITTEST messages
  801. (no matter where you move the moust) while the mouse is
  802. captured. 
  803.  
  804. Submitted by V. Ramachandran
  805.  
  806.  
  807. ------------------------------------------------------------
  808.  
  809. WDJ SDK Annotation #39
  810. TYPE:       Win3.1
  811. TOPIC:      TabbedTextOut (3.0)
  812. KEYWORD:    TabbedTextOut
  813.  
  814. The documentation claims that the tab stops are in device
  815. units (pixels), but that is not true.  The tab stops are
  816. treated as logical units, not device units. 
  817.  
  818. Submitted by Dan Miser^
  819. Reference: Microsoft Knowledge Base article Q113253
  820.  
  821.  
  822. ------------------------------------------------------------
  823.  
  824. WDJ SDK Annotation #40
  825. TYPE:       Win3.1
  826. TOPIC:      LoadIcon (2.x)
  827. KEYWORD:    LoadIcon
  828.  
  829. The documentation says that you should call DestroyIcon()
  830. for cursors loaded via LoadIcon().  That is wrong -- you
  831. should only call DestroyIcon() for icons created with
  832. CreateIcon(). 
  833.  
  834. Submitted by Charles Leamon^
  835. Reference: Microsoft Knowledge Base article Q84779
  836.  
  837.  
  838. ------------------------------------------------------------
  839.  
  840. WDJ SDK Annotation #41
  841. TYPE:       Win3.1
  842. TOPIC:      COMPAREITEMSTRUCT (3.0)
  843. KEYWORD:    COMPAREITEMSTRUCT
  844.  
  845. Note that Windows has to send a WM_COMPAREITEM message when
  846. a new item is added to the list, in order to determine its
  847. correct position.  That means it does not know the position
  848. of the new item yet, so (contrary to the documentation) the
  849. itemID2 field in this structure will be -1 -- do not assume
  850. it will be a legal index value. 
  851.  
  852. Submitted by V. Ramachandran
  853.  
  854.  
  855. ------------------------------------------------------------
  856.  
  857. WDJ SDK Annotation #42
  858. TYPE:       Win3.1
  859. TOPIC:      GetProcAddress (2.x)
  860. KEYWORD:    GetProcAddress
  861.  
  862. In attempting to locate the named function in the target
  863. module, GetProcAddress() converts the function name to
  864. uppercase and then performs a case-sensitive search.  That
  865. means that GetProcAddress() cannot locate functions exported
  866. with names containing lowercase characters.  Normally,
  867. that's not a problem, as the __pascal calling sequence
  868. forces uppercase names.  However, depending on the compiler
  869. and linker tools and options you use, it is possible to
  870. export __cdecl calling sequence functions with lowercase
  871. characters, resulting in a function that GetProcAddress()
  872. cannot locate. 
  873.  
  874. Submitted by Keith Bluestone
  875.  
  876. ------------------------------------------------------------
  877.  
  878. WDJ SDK Annotation #43
  879. TYPE:       Win3.1
  880. TOPIC:      SetScrollRange (2.x)
  881. KEYWORD:    SetScrollRange
  882.  
  883. The documentation says you can use this function to hide or
  884. show standard scroll bars, but does not tell you how!
  885. Basically, if you specify the same value for both the
  886. minimum (nMin) and maximum (nMax) scrolling positions, the
  887. function will hide the scroll bar.  If the two positions are
  888. not equal, the function will display the scroll bar. 
  889.  
  890. Submitted by Paul Bonneau
  891.  
  892.  
  893. ------------------------------------------------------------
  894.  
  895. WDJ SDK Annotation #44
  896. TYPE:       Win3.1
  897. TOPIC:      LoadLibrary (2.x)
  898. KEYWORD:    LoadLibrary
  899.  
  900. If LoadLibrary() cannot find the library, it may display an
  901. error message to the user, depending upon the state of
  902. Windows' "error mode".  If you want to handle that case
  903. yourself and make sure Windows does not display the error
  904. message, see the documentation for the function
  905. SetErrorMode().  For example, the following code attempts to
  906. load the library ctl3d.dll, but does not emit an error
  907. message if it is not found. 
  908.  
  909. HINSTANCE Ctl3d;^
  910. UINT OldFlag = SetErrorMode(SEM_NOOPENFILEERRORBOX);^
  911. Ctl3d        = LoadLibrary("ctl3d.dll");^
  912. SetErrorMode(OldFlag);  // restore previous mode^
  913. if(Ctl3d <= HINSTANCE_ERROR)^
  914.     // LoadLibrary() failed for some reason^
  915.  
  916.  
  917. ------------------------------------------------------------
  918.  
  919. WDJ SDK Annotation #45
  920. TYPE:       Win3.1
  921. TOPIC:      LoadLibrary (2.x)
  922. KEYWORD:    LoadLibrary
  923.  
  924.  
  925. The documentation claims this function returns an error code
  926. of 0 if "System was out of memory, executable file was
  927. corrupt, or relocations were invalid".  However, if a
  928. library's LibMain() function returns 0 (signifying some
  929. logical error during initialization), LoadLibrary() also
  930. returns 0.  Therefore, do not assume that a 0 error code
  931. means the system was out of memory or that the module was
  932. corrupt in some way. 
  933.  
  934.  
  935. ------------------------------------------------------------
  936.  
  937. WDJ SDK Annotation #46
  938. TYPE:       Win3.1
  939. TOPIC:      DdeClientTransaction (3.1)
  940. KEYWORD:    DdeClientTransaction
  941.  
  942. The documentation does not say so, but the cbData argument
  943. (length of data) must include the NULL byte if the data is a
  944. string.  In other words, if lpvData is a string, cbData must
  945. be set to strlen(lpvData)+1.  Otherwise, bad things may
  946. happen in DDEML when you perform an XTYP_POKE or
  947. XTYP_EXECUTE. 
  948.  
  949. Submitted by Mark Reha^
  950. Reference: Microsoft Knowledge Base article Q107387.
  951.  
  952.  
  953. ------------------------------------------------------------
  954.  
  955. WDJ SDK Annotation #47
  956. TYPE:       Win3.1
  957. TOPIC:      WinHelp (3.0)
  958. KEYWORD:    WinHelp
  959.  
  960. The WinHelp() API function normally allows one to execute
  961. macros, jumps, popups, and so on.  However, if WinHelp was
  962. started with WinExec() (i.e.  from Program Manager or File
  963. Manager) instead of the WinHelp() API function, you will not
  964. be able to execute macros or jumps on that help file without
  965. starting up a second instance of the help file using the
  966. WinHelp() API function. 
  967.  
  968. There is one way around this.  You can create a DLL with an
  969. LDLLHandler that gets the callback address for the FAPI()
  970. function from WinHelp.  FAPI() has the same parameters as
  971. the WinHelp() API function except that the first parameters
  972. (HWND) is not in FAPI() (so FAPI() only has 3 parameters). 
  973. The FAPI() function will allow you to execute macros, jumps,
  974. popups, etc regardless of how WinHelp was launched.  For
  975. more information, get the Windows Help Authors Guide from
  976. the MSDN CD-ROM or see Jim Mischel's book "The Developer's
  977. Guide to WINHELP.EXE". 
  978.  
  979. Submitted by Pete Davis
  980.  
  981.  
  982. ------------------------------------------------------------
  983.  
  984. WDJ SDK Annotation #48
  985. TYPE:       Win3.1
  986. TOPIC:      _fpmath (2.x)
  987. KEYWORD:    _fpmath
  988.  
  989. When setting the handler for coprocessor error exceptions
  990. (function 3), the documentation incorrectly says you should
  991. place the address of your exception handler in DS:AX.  The
  992. correct registers to use for this 32-bit address are DX:AX. 
  993.  
  994. Submitted by Manfred Keul
  995.  
  996.  
  997. ------------------------------------------------------------
  998.  
  999. WDJ SDK Annotation #49
  1000. TYPE:       Win3.1
  1001. TOPIC:      VerQueryValue (3.1)
  1002. KEYWORD:    VerQueryValue
  1003.  
  1004. Amazingly, even though the second parameter to this function
  1005. is declared const (LPCSTR), VerQueryValue() modifies that
  1006. string anyway! Apparently the code replaces a '\' in your
  1007. string with a NULL byte temporarily and then puts it back. 
  1008. This is a bug.  For example, suppose you use a compiler
  1009. option that places constant strings in read-only code
  1010. segments (for Microsoft, "/Gf"; for Borland "-dc").  In that
  1011. case, passing such a constant string as the second argument
  1012. to this function results in a GP fault. 
  1013.  
  1014. Submitted by David Lowndes
  1015.  
  1016.  
  1017. ------------------------------------------------------------
  1018.  
  1019. WDJ SDK Annotation #50
  1020. TYPE:       Win3.1
  1021. TOPIC:      GetProfileString (2.x)
  1022. KEYWORD:    GetProfileString
  1023.  
  1024. This applies to both GetProfileString() and
  1025. GetPrivateProfileString().  If the default value for these
  1026. functions contains trailing blanks and the default value is
  1027. used because the key did not appear in the INI file, Windows
  1028. will null-terminate the string (even though it is declared
  1029. const!) at the first trailing blank.  If that string is a
  1030. literal string and the code is compiled with some
  1031. optimizations then the string will end up in a code segment,
  1032. resulting in a GPF when the API function attempts to modify
  1033. it.
  1034.  
  1035. GetProfileString() and GetPrivateProfileString() also strip
  1036. out any leading spaces, and any leading and trailing quotes
  1037. (single or double quotes).
  1038.  
  1039. Submitted by Michael E. Kropp.^
  1040. Revised by Kai Riihioja
  1041.  
  1042.  
  1043.  
  1044.  
  1045. ------------------------------------------------------------
  1046.  
  1047. WDJ SDK Annotation #50
  1048. TYPE:       Win3.1
  1049. TOPIC:      GetPrivateProfileString (2.x)
  1050. KEYWORD:    GetPrivateProfileString
  1051.  
  1052. This applies to both GetProfileString() and
  1053. GetPrivateProfileString().  If the default value for these
  1054. functions contains trailing blanks and the default value is
  1055. used because the key did not appear in the INI file, Windows
  1056. will null-terminate the string (even though it is declared
  1057. const!) at the first trailing blank.  If that string is a
  1058. literal string and the code is compiled with some
  1059. optimizations then the string will end up in a code segment,
  1060. resulting in a GPF when the API function attempts to modify
  1061. it.
  1062.  
  1063. GetProfileString() and GetPrivateProfileString() also strip
  1064. out any leading spaces, and any leading and trailing quotes
  1065. (single or double quotes).
  1066.  
  1067. Submitted by Michael E. Kropp.^
  1068. Revised by Kai Riihioja
  1069.  
  1070.  
  1071.  
  1072.  
  1073. ------------------------------------------------------------
  1074.  
  1075. WDJ SDK Annotation #51
  1076. TYPE:       Win3.1
  1077. TOPIC:      GetTickCount (2.x)
  1078. KEYWORD:    GetTickCount
  1079.  
  1080. GetTickCount() may return units of milliseconds, but its
  1081. resolution is much worse than one millisecond under Windows
  1082. 3.1.  For more accurate timings, call the function
  1083. timeGetTime(), which is defined in mmsystem.h. 
  1084.  
  1085.  
  1086.  
  1087. ------------------------------------------------------------
  1088.  
  1089. WDJ SDK Annotation #52
  1090. TYPE:       Win3.1
  1091. TOPIC:      GetWinFlags (3.0)
  1092. KEYWORD:    GetWinFlags
  1093.  
  1094. GetWinFlags() can also tell you if your 16-bit Windows 3.1
  1095. application is running under Windows NT:
  1096.  
  1097.     if(GetWinFlags() & 0x04000)^
  1098.         // then we are running under Windows NT^
  1099.  
  1100. Submitted by Paula Tomlinson.^
  1101. Reference: "The Ultimate Windows Version Detector",
  1102. Windows/DOS Developer's Journal, February 1995. 
  1103.  
  1104.  
  1105. ------------------------------------------------------------
  1106.  
  1107. WDJ SDK Annotation #53
  1108. TYPE:       Win3.1
  1109. TOPIC:      KillTimer (2.x)
  1110. KEYWORD:    KillTimer
  1111.  
  1112. Under at least one condition, KillTimer() does not remove a
  1113. pending WM_TIMER message from the message queue as
  1114. documented.  First, understand that Windows just sets a bit
  1115. when a timer fires; it does not generate a WM_TIMER message
  1116. at that time.  A timer message is secretly added to your
  1117. input queue when you call GetMessage() or PeekMessage() and
  1118. a timer event is pending and no other messages are in the
  1119. queue. 
  1120.  
  1121. If you are using a PeekMessage() call with the PM_NOREMOVE
  1122. flag and if the timer bit is on at that point, PeekMessage()
  1123. will place a WM_TIMER message in the queue, but won't remove
  1124. it.  If you then call KillTimer(), it will ensure the timer
  1125. bit is off but won't remove the WM_TIMER message.  The next
  1126. call to GetMessage() or PeekMessage() returns this WM_TIMER
  1127. message.  One workaround is to use code like this to
  1128. terminate a timer:
  1129.  
  1130.     KillTimer (hWnd, ID);^
  1131.     if (LOWORD (GetQueueStatus (QS_TIMER)) & QS_TIMER)^
  1132.          PeekMessage (&msg, hWnd, WM_TIMER, WM_TIMER, PM_REMOVE);^
  1133.  
  1134. Submitted by Mike Mast.
  1135.  
  1136.  
  1137. ------------------------------------------------------------
  1138.  
  1139. WDJ SDK Annotation #54
  1140. TYPE:       Win3.1
  1141. TOPIC:      DEVMODE (3.0)
  1142. KEYWORD:    DEVMODE
  1143.  
  1144. The documentation claims that DMCOLOR_COLOR is defined to be
  1145. 1 and DMCOLOR_MONOCHROME is defined to be 2.  In fact, if
  1146. you look in print.h you discover that the reverse is true. 
  1147.  
  1148. Submitted by Bill Liu.
  1149.  
  1150.  
  1151.  
  1152. ------------------------------------------------------------
  1153.  
  1154. WDJ SDK Annotation #55
  1155. TYPE:       Win3.1
  1156. TOPIC:      EN_CHANGE (2.x)
  1157. KEYWORD:    EN_CHANGE
  1158.  
  1159. The documentation implies this notification only arises from
  1160. actions by the user.  In fact, this notification also arises
  1161. from programmatic changes, such as from sending a WM_SETTEXT
  1162. message to the edit control, or using SetWindowText() (which
  1163. sends a WM_SETTEXT message).  Not knowing this, you might
  1164. code an EN_CHANGE handler that attempts to modify the edit
  1165. control text, resulting in another EN_CHANGE notification --
  1166. an infinite loop!
  1167.  
  1168. Submitted by Scott Smith.
  1169.  
  1170.  
  1171. ------------------------------------------------------------
  1172.  
  1173. WDJ SDK Annotation #56
  1174. TYPE:       Win3.1
  1175. TOPIC:      EnumFonts (2.x)
  1176. KEYWORD:    EnumFonts
  1177.  
  1178. The 3.1 documentation for this function specifies that the
  1179. third argument is of type FONTENUMPROC.  This was true in
  1180. previous versions, but in 3.1 this call is deprecated in
  1181. favour of the new EnumFontFamilies() API function.  The
  1182. definition of the FONTENUMPROC type has been updated to take
  1183. a NEWTEXTMETRIC parameter, and therefore no longer quite
  1184. matches the prototype specified for EnumFonts.  Microsoft
  1185. provids a new type, OLDFONTENUMPROC, which corresponds to
  1186. the STRICT definition of EnumFonts in windows.h, but this is
  1187. not reflected in the documentation.  In other words, if you
  1188. compile with STRICT defined for Windows 3.1 and want to use
  1189. EnumFonts(), make sure the third parameter is of type
  1190. OLDFONTENUMPROC. 
  1191.  
  1192. Submitted by David W. Gillett.
  1193.  
  1194.  
  1195. ------------------------------------------------------------
  1196.  
  1197. WDJ SDK Annotation #57
  1198. TYPE:       Win3.1
  1199. TOPIC:      PtInRect (2.x)
  1200. KEYWORD:    PtInRect
  1201.  
  1202. There is no mention of this, but the rectangle MUST be
  1203. normailized before this function is called.  In other words,
  1204. you have to make sure that lprc->right is greater than
  1205. lprc->left, and that lrpc->bottom is greater than lrpc->top. 
  1206. Otherwise, the point will never be considered inside of the
  1207. rectangle.  By contrast, the function RectInRegion() does
  1208. accept and correctly handle all rectangles, whether
  1209. normalized or not. 
  1210.  
  1211. Submitted by Peter Ritchie.
  1212.  
  1213.  
  1214. ------------------------------------------------------------
  1215.  
  1216. WDJ SDK Annotation #58
  1217. TYPE:       Win3.1
  1218. TOPIC:      SetTimer (2.x)
  1219. KEYWORD:    SetTimer
  1220.  
  1221. The documentation makes it sound like Windows either posts a
  1222. message (if you supply no callback function) or else calls
  1223. your callback function directly when the timer expires.  In
  1224. fact, when the timer fires, Windows sets a bit in your
  1225. message queue which gets transformed into a WM_TIMER message
  1226. by either GetMessage() or PeekMessage() when they find no
  1227. other messages in the input queue.  The WM_TIMER message
  1228. contains the address of your callback function (if any),
  1229. which will be called by DefWindowProc() after the message is
  1230. dispatched to your window.  The key point here is that the
  1231. timers created by SetTimer() are always message based
  1232. (Windows does not call your timer procedure asynchronously)
  1233. and of a lower priority than any other Windows message. 
  1234.  
  1235. Submitted by Alan M. Carroll.
  1236.  
  1237.  
  1238.  
  1239. ------------------------------------------------------------
  1240.  
  1241. WDJ SDK Annotation #59
  1242. TYPE:       Win3.1
  1243. TOPIC:      lstrcpy (2.x)
  1244. KEYWORD:    lstrcpy
  1245.  
  1246. Believe it or not, this function (and apparently other
  1247. similar functions) examine the limit of the selector of the
  1248. output string, and even attempt to silently recover if the
  1249. operation causes a GP fault.  As a consequence, you should
  1250. not count on this function being a real speed demon. 
  1251.  
  1252. Submitted by Vivek Venugopalan
  1253.  
  1254. ------------------------------------------------------------
  1255.  
  1256. WDJ SDK Annotation #60
  1257. TYPE:       Win3.1
  1258. TOPIC:      GetModuleFileName (2.x)
  1259. KEYWORD:    GetModuleFileName
  1260.  
  1261. Windows 3.1 has a bug that causes this function to sometimes
  1262. return relative paths instead of absolute (fully qualified)
  1263. paths.This error occurs if a relative path is specified in
  1264. the PATH variable, and the DLL is implicitly loaded from
  1265. this directory.  For example, if the PATH variable is:
  1266.  
  1267.     PATH=C:\DOS;D:.;C:\UTILS
  1268.  
  1269. and an application running from any other directory but
  1270. "D:.", loads a DLL (test.dll) in "D:." implicitly (since it
  1271. is in the path), then a call to GetModuleFileName() with the
  1272. DLL instance will return "D:.\test.dll". 
  1273.  
  1274. Submitted by V. Ramachandran
  1275. Reference: MSKB PSS ID Number: Q85330.
  1276.  
  1277. ------------------------------------------------------------
  1278.  
  1279. WDJ SDK Annotation #61
  1280. TYPE:       Win3.1
  1281. TOPIC:      CB_GETDROPPEDCONTROLRECT (3.1)
  1282. KEYWORD:    CB_GETDROPPEDCONTROLRECT
  1283.  
  1284. The documentation claims that this function retrieves the
  1285. screen coordinates of the listbox portion of a combo box. 
  1286. In fact, it retrieves the screen coordinates of the
  1287. rectangle that encloses the ENTIRE combo box in its
  1288. dropped-down state.  That means the rectangle retrieved is
  1289. both bit taller and a bit wider than the rectangle that the
  1290. help file claims is returned. 
  1291.  
  1292. Submitted by V. Ramachandran
  1293.  
  1294.  
  1295. ------------------------------------------------------------
  1296.  
  1297. WDJ SDK Annotation #62
  1298. TYPE:       Win3.1
  1299. TOPIC:      NotifyUnRegister (3.1)
  1300. KEYWORD:    NotifyUnRegister
  1301.  
  1302. As the documentation says, you can set the htask argument to
  1303. NULL to refer to the current task.  This is probably not a
  1304. good practice, however.  If more than one application can
  1305. load your DLL, then there is typically some scenario under
  1306. which the task that you called NotifyRegister() for has died
  1307. before you call NotifyUnRegister(), in which case passing
  1308. NULL would refer to the wrong task.  It's probably safer to
  1309. explicitly store that task that was passed to
  1310. NotifyRegister() and make sure you pass the same task to
  1311. NotifyUnregister(). 
  1312.  
  1313. Submitted by Paul Dolphin.
  1314.  
  1315.  
  1316. ------------------------------------------------------------
  1317.  
  1318. WDJ SDK Annotation #63
  1319. TYPE:       Win3.1
  1320. TOPIC:      CreateCompatibleDC (2.x)
  1321. KEYWORD:    CreateCompatibleDC
  1322.  
  1323. You might think from the name that this function returns a
  1324. device context whose attributes are the same as the source
  1325. device context.  In fact, attributes such as the mapping
  1326. mode will be set to their defaults (e.g., the mapping mode
  1327. will always be MM_TEXT) in the returned device context, not
  1328. to the attribute values of the source device context. 
  1329.  
  1330. Submitted by Stuart Patterson^
  1331. Reference: p.  624, "Programming Windows 3.1, 3rd Edition",
  1332. by Charles Petzold
  1333.  
  1334.  
  1335.  
  1336. ------------------------------------------------------------
  1337.  
  1338. WDJ SDK Annotation #64
  1339. TYPE:       Win3.1
  1340. TOPIC:      Device Contexts
  1341. KEYWORD:    Device Contexts
  1342.  
  1343. The help file says CreateCompatibleDC() creates a device
  1344. context that "has the same attributes" as the source device
  1345. context.  In fact, the device context's attributes (such as
  1346. mapping mode) will have their default values, no matter what
  1347. value they had in the source device context. 
  1348.  
  1349. Submitted by Stuart Patterson^
  1350. Reference: p.  624, "Programming Windows 3.1, 3rd Edition",
  1351. by Charles Petzold
  1352.  
  1353. ------------------------------------------------------------
  1354.  
  1355. WDJ SDK Annotation #65
  1356. TYPE:       Win3.1
  1357. TOPIC:      UngetCommChar (2.x)
  1358. KEYWORD:    UngetCommChar
  1359.  
  1360. Do not use this function under Windows 3.1 -- it causes lost
  1361. characters or even GP faults!
  1362.  
  1363. Submitted by Manfred Keul.^
  1364. Reference: Microsoft Knowledge Base article Q100183.
  1365.  
  1366.  
  1367.  
  1368. ------------------------------------------------------------
  1369.  
  1370. WDJ SDK Annotation #66
  1371. TYPE:       Win3.1
  1372. TOPIC:      TabbedTextOut (3.0)
  1373. KEYWORD:    TabbedTextOut
  1374.  
  1375. If a tab character is the last character in the string, then
  1376. all of the area to the next tab stop is filled with the
  1377. current background color.  This may or may not be the
  1378. behavior you want in any given situation. 
  1379.  
  1380. Submitted by Tim English.
  1381.  
  1382. ------------------------------------------------------------
  1383.  
  1384. (Note: due to a bug in WinHelp, it is not possible to display
  1385. or annotate the GetRgnBox topic in the Visual C++ v1.5
  1386. version of the helpfile)
  1387.  
  1388. WDJ SDK Annotation #67
  1389. TYPE:       Win3.1
  1390. TOPIC:      GetRgnBox (3.0)
  1391. KEYWORD:    GetRgnBox
  1392.  
  1393. The documentation claims GetRgnBox() returns COMPLEXREGION
  1394. when the region has overlapping borders.  In fact,
  1395. GetRgnBox() apparently returns COMPLEXREGION if the region
  1396. is simply non-rectangular, whether overlapping borders are
  1397. involved or not. 
  1398.  
  1399. Submitted by Jason Douglas.
  1400.  
  1401. ------------------------------------------------------------
  1402.  
  1403. WDJ SDK Annotation #68
  1404. TYPE:       Win3.1
  1405. TOPIC:      DRAWITEMSTRUCT (3.0)
  1406. KEYWORD:    DRAWITEMSTRUCT
  1407.  
  1408. The itemID field in this structure is set to a negative value
  1409. for an empty listbox or combobox.  Watch out, though -- since
  1410. this field is defined to be unsigned (UINT), a statement like
  1411. this:
  1412.  
  1413.     if(lpdis->itemID >= 0) // if listbox not empty^
  1414.         // ... some code^
  1415.  
  1416. will always evaluate true.  To check for an empty listbox or
  1417. combobox, either cast the field to int or check the high bit:
  1418.  
  1419.     if( (int) lpdis->itemID  >= 0)  // this works correctly^
  1420.         //... some code^
  1421.  
  1422. Submitted by Aaron O'Neil.
  1423.  
  1424.  
  1425. ------------------------------------------------------------
  1426.  
  1427.  
  1428. WDJ SDK Annotation #69
  1429. TYPE:       Win3.1
  1430. TOPIC:      DDEDATA (2.x)
  1431. KEYWORD:    DDEDATA
  1432.  
  1433. In this help topic, the description for the fResponse field
  1434. actually describes the fAckReq field, and vice versa. 
  1435.  
  1436. Submitted by Sudhir Menon.^
  1437. Reference: Microsoft Knowledge Base article Q93372.
  1438.  
  1439. ------------------------------------------------------------
  1440.  
  1441. WDJ SDK Annotation #70
  1442. TYPE:       Win3.1
  1443. TOPIC:      EnableCommNotification (3.1)
  1444. KEYWORD:    EnableCommNotification
  1445.  
  1446. Due to bugs in Windows 3.1, you will probably want to always set
  1447. both cbWriteNotify and cbOutQueue to -1, thus disabling the
  1448. CN_TRANSMIT and CN_RECEIVE notifications.  If you do not set
  1449. them to -1, spurious WM_COMMNOTIFY messages can be sent,
  1450. resulting in a system crash at higher baud rates. 
  1451.  
  1452. Submitted by Manfred Keul.^
  1453. Reference: Microsoft Knowledge Base article Q101420.
  1454.  
  1455.  
  1456.  
  1457. ------------------------------------------------------------
  1458.  
  1459. WDJ SDK Annotation #71
  1460. TYPE:       Win3.1
  1461. TOPIC:      GetMsgProc (3.1)
  1462. KEYWORD:    GetMsgProc
  1463.  
  1464. The help file fails to mention that your hook function gets
  1465. called by PeekMessage(), not just by GetMessage().  The
  1466. documentation also contradicts itself, saying first that wParam
  1467. is undefined and later saying that wParam is NULL.  The
  1468. Microsoft Knowledge Base, on the other hand, reveals that wParam
  1469. contains the PM_ flags that were used in the call to
  1470. PeekMessage(), so your message hook can, for example, determine
  1471. if the message was being removed or not with code like this:
  1472.  
  1473.     if(wParam & PM_REMOVE)^
  1474.         //... then message is being removed^
  1475.     else^
  1476.         //... message is not being removed^
  1477.  
  1478. Note that your hook may want to ignore the message if it is not
  1479. being removed, since your hook will get called again when the
  1480. same message is removed by some future call to GetMessage() or
  1481. PeekMessage(). 
  1482.  
  1483. Submitted by V. Ramachandran.^
  1484. Reference: Microsoft Knowledge Base article Q104068
  1485.  
  1486.  
  1487. ------------------------------------------------------------
  1488.  
  1489. WDJ SDK Annotation #72
  1490. TYPE:       Win3.1
  1491. TOPIC:      GetInstanceData (2.x)
  1492. KEYWORD:    GetInstanceData
  1493.  
  1494. Both the documentation and windows.h declare the second
  1495. parameter as a BYTE*.  Unfortunately, that declaration is only
  1496. correct if you are using a memory model with near data (small or
  1497. medium memory models), and will be incorrect for large or huge
  1498. memory models.  The correct declaration for this argument is
  1499. BYTE NEAR*. 
  1500.  
  1501. Submitted by Martin Cooper.
  1502.  
  1503.  
  1504. ------------------------------------------------------------
  1505.  
  1506. WDJ SDK Annotation #73
  1507. TYPE:       Win3.1
  1508. TOPIC:      MENUITEMTEMPLATE (3.0)
  1509. KEYWORD:    MENUITEMTEMPLATE
  1510.  
  1511. Missing from the list of bits you can turn on in mtOption is
  1512. MF_END (0x0080), which indicates that the item terminates
  1513. the menu.
  1514.  
  1515. Submitted by V. Ramachandran.
  1516.  
  1517.  
  1518.  
  1519. ------------------------------------------------------------
  1520.  
  1521. WDJ SDK Annotation #74
  1522. TYPE:       Win3.1
  1523. TOPIC:      AddAtom (2.x)
  1524. KEYWORD:    AddAtom
  1525.  
  1526. AddAtom() handles strings that begin with "#" specially:
  1527. it expects the string following the "#" to be a string
  1528. of digits, and returns an atom is value is the 16-bit
  1529. binary representation of that string of digits. Unfortunately,
  1530. if your first call to AddAtom() is with a string like "#nondigits",
  1531. it will produce a divide by zero fault. Two workarounds
  1532. are possible: either make sure your first call to AddAtom()
  1533. does not contain such a string, or call InitAtomTable()
  1534. before calling AddAtom() for the first time.
  1535.  
  1536. Submitted by V. Ramachandran.^
  1537. Reference: MSKB PSS ID Number: Q103036
  1538.  
  1539.  
  1540. ------------------------------------------------------------
  1541.  
  1542.  
  1543. WDJ SDK Annotation #75
  1544. TYPE:       Win3.1
  1545. TOPIC:      DCB (2.x)
  1546. KEYWORD:    DCB
  1547.  
  1548. When setting the BaudRate field, do not use the constant
  1549. CBR_14400; Windows 3.1's COMM.DRV has a bug that will produce
  1550. communications problems due to a bad table entry for that
  1551. constant.  Instead, set BaudRate to the integer 14400 to
  1552. communicate at 14400 baud. 
  1553.  
  1554. Submitted by Manfred Keul.^
  1555. Reference: Microsoft Knowledge Base article Q83232.
  1556.  
  1557.  
  1558. ------------------------------------------------------------
  1559.  
  1560. WDJ SDK Annotation #76
  1561. TYPE:       Win3.1
  1562. TOPIC:      RegisterRoutine WinHelp macro
  1563. KEYWORD:    RegisterRoutine WinHelp macro
  1564.  
  1565. The documentation does not reveal how to specify the return type
  1566. of the function. You do this by inserting a type-specifying
  1567. character followed by an equal sign in the third parameter
  1568. string. For example, to register FindWindow() (which takes
  1569. two far strings and returns a 16-bit unsigned integer), you
  1570. might use:
  1571.  
  1572.     RR("USER", "FindWindow", "u=SS");
  1573.  
  1574. Note that if you do not specify a return type when you register
  1575. a function, you cannot use that function in an IfThen or
  1576. IfThenElse macro.
  1577.  
  1578. Submitted by Sudhir Menon.
  1579.  
  1580. ------------------------------------------------------------
  1581.  
  1582. WDJ SDK Annotation #77
  1583. TYPE:       Win3.1
  1584. TOPIC:      RTF Tokens
  1585. KEYWORD:    RTF Tokens
  1586.  
  1587. Strangely, the tokens "emc", "eml", and "emr" are
  1588. misspelled in the online help -- they should be
  1589. "ewc", "ewl", and "ewr", where the "ew" stands for
  1590. Embedded Window. Note that this are not really RTF
  1591. tokens, but literal text. The help compiler scans
  1592. for any text you have entered of the form "{ewx commands}"
  1593. in order to detect embedded window commands. Such text,
  1594. when translated by your word processor into RTF, looks
  1595. like this: "\{ewx commands\}".
  1596.  
  1597. Submitted by John Sawyer.
  1598.  
  1599.  
  1600. ------------------------------------------------------------
  1601.  
  1602. WDJ SDK Annotation #78
  1603. TYPE:       Win3.1
  1604. TOPIC:      WM_ENTERIDLE (2.x)
  1605. KEYWORD:    WM_ENTERIDLE
  1606.  
  1607. Note that you can elect to suppress the WM_ENTERIDLE
  1608. message for a particular modal dialog box by defining
  1609. it with the DS_NOIDLEMSG window style bit.
  1610.  
  1611. Submitted by V. Ramachandran.
  1612.  
  1613.  
  1614. ------------------------------------------------------------
  1615.  
  1616. WDJ SDK Annotation #79
  1617. TYPE:       Win3.1
  1618. TOPIC:      WM_SYSCOMMAND (2.x)
  1619. KEYWORD:    WM_SYSCOMMAND
  1620.  
  1621. You can use this message with SC_MENUKEY to simulate the
  1622. user selecting a menu with an accelerator key.  For example,
  1623. to simulate the user accessing the "File" menu, you might
  1624. use the following code:
  1625.  
  1626. PostMessage(hWnd, WM_SYSCOMMAND, SC_MENUKEY, MAKELPARAM('f',0));
  1627.  
  1628. Submitted by Jay Giganti.
  1629.  
  1630.  
  1631. ------------------------------------------------------------
  1632.  
  1633. WDJ SDK Annotation #80
  1634. TYPE:       Win3.1
  1635. TOPIC:      wsprintf
  1636. KEYWORD:    wsprintf
  1637.  
  1638. The documentation says the second parameter is an LPSTR,
  1639. but it is actually an LPCSTR (and so declared in windows.h),
  1640. so it's safe to use a string constant.
  1641.  
  1642. Submitted by: V. Ramachandran.
  1643.  
  1644.  
  1645. ------------------------------------------------------------
  1646.  
  1647. WDJ SDK Annotation #81
  1648. TYPE:       Win3.1
  1649. TOPIC:      _lread (2.x)
  1650. KEYWORD:    _lread
  1651.  
  1652. If you call _lread() to read a floppy when there is no
  1653. diskette in the drive, Windows puts up a system error
  1654. message box ("Cannot Read from Drive...") with Retry and
  1655. Cancel buttons.  If the user presses the Cancel button,
  1656. _lread() returns a non-negative number, indicating success. 
  1657. It should return HFILE_ERROR instead. 
  1658.  
  1659. To avoid this error, call SetErrorMode(SEM_NOOPENFILEERRORBOX)
  1660. before calling _lread(), then it will correctly return -1 on
  1661. failure. 
  1662.  
  1663. Submitted by: V. Ramachandran.^
  1664. Reference: MSDN PSS ID No. Q111587.
  1665.  
  1666.  
  1667. ------------------------------------------------------------
  1668.  
  1669. WDJ SDK Annotation #82
  1670. TYPE:       Win3.1
  1671. TOPIC:      WM_COMPAREITEM (3.0)
  1672. KEYWORD:    WM_COMPAREITEM
  1673.  
  1674. The documentation for WM_COMPAREITEM says that the parent of
  1675. owner-drawn listboxes with the LBS_SORT (or CBS_SORT) styles
  1676. will get this message in order to determine the relative
  1677. position.  However, Windows will not send the WM_COMPAREITEM
  1678. message if the LBS_HASSTRINGS style bit is set, even if it
  1679. is an owner-drawn listbox with the LBS_SORT style. The same
  1680. is true for comboboxes.
  1681.  
  1682. Submitted by: V. Ramachandran.
  1683.  
  1684.  
  1685. ------------------------------------------------------------
  1686.  
  1687. WDJ SDK Annotation #83
  1688. TYPE:       Win3.1
  1689. TOPIC:      DOCINFO (3.1)
  1690. KEYWORD:    DOCINFO
  1691.  
  1692. The documentation fails to point out that lpszOutput is
  1693. limited to 32 characters, including the null terminating
  1694. byte.  If you use a string longer than that, the trailing
  1695. characters will be ignored.  For example, if you use a
  1696. string containing the too-long path:
  1697.  
  1698.     c:\usr\ts\issues\pending\12345678\abcdefgh.out
  1699.  
  1700. the actual file that gets created will be:
  1701.  
  1702.     c:\usr\ts\issues\pending\123456
  1703.  
  1704. Submitted by V. Ramachandran.
  1705.  
  1706.  
  1707.  
  1708.  
  1709. ------------------------------------------------------------
  1710.  
  1711. WDJ SDK Annotation #84
  1712. TYPE:       Win3.1
  1713. TOPIC:      SetAbortProc function
  1714. KEYWORD:    SetAbortProc
  1715.  
  1716.  
  1717. SetAbortProc() returns a negative value, which is documented
  1718. as indicating failure.  However, the return value from
  1719. SetAbortProc does not indicate success or failure of the
  1720. function, so don't depend on the return value for anything.
  1721.  
  1722. Submitted by:    V. Ramachandran.^
  1723. Reference:    MSDN PSS ID No. Q109540.
  1724.  
  1725.  
  1726. ------------------------------------------------------------
  1727.  
  1728. WDJ SDK Annotation #85
  1729. TYPE:       Win3.1
  1730. TOPIC:      BN_DISABLE (2.x)
  1731. KEYWORD:    BN_DISABLE
  1732.  
  1733. The documentation claims the button sends this notification
  1734. whenever it gets disabled. In fact, Windows 3.1 buttons do
  1735. not appear to ever send this notification!
  1736.  
  1737. Submitted by: V. Ramachandran.
  1738.  
  1739.  
  1740.  
  1741.  
  1742.  
  1743.  
  1744. ------------------------------------------------------------
  1745.  
  1746. WDJ SDK Annotation #86
  1747. TYPE:       Win3.1
  1748. TOPIC:      BN_DOUBLECLICKED (2.x)
  1749. KEYWORD:    BN_DOUBLECLICKED
  1750.  
  1751. The documentation fails to point out that this notification
  1752. is only sent for buttons that have the BS_OWNERDRAW or
  1753. BS_RADIOBUTTON styles. No other types of buttons generate
  1754. this notification
  1755.  
  1756. Submitted by: V. Ramachandran.
  1757.  
  1758.  
  1759.  
  1760. ------------------------------------------------------------
  1761.  
  1762. WDJ SDK Annotation #87
  1763. TYPE:       Win3.1
  1764. TOPIC:      WM_DROPFILES (3.1)
  1765. KEYWORD:    WM_DROPFILES
  1766.  
  1767. Documentation for the undocumented handle has since been
  1768. published by Microsoft in Microsoft Systems Journal.  This
  1769. handle points to a structure like this:
  1770.  
  1771. typedef struct {^
  1772.     int     wSize;          // Number of bytes in this structure^
  1773.     POINT   ptMousePos;     // Mouse position^
  1774.     BOOL    fInNonClientArea;// TRUE if mouse was in client area^
  1775.     // Pathnames begin after structure each one zero-terminated^
  1776.     // Zero-length pathname used to indicate the end^
  1777. } DROPFILESTRUCT, FAR *LPDROPFILESTRUCT;^
  1778.  
  1779. The Win32 version of this structure is slightly different.  The
  1780. first field becomes a 4-byte rather than a 2-byte integer, and
  1781. the structure contains an additional BOOL field at the end that
  1782. is TRUE if the pathnames are in Unicode rather than ANSI
  1783. strings. 
  1784.  
  1785. Submitted by V. Ramachandran.^
  1786. Reference:  May/June 1992 Microsoft Systems Journal^
  1787.             February 1994 Microsoft Systems Journal
  1788.  
  1789.  
  1790.  
  1791. ------------------------------------------------------------
  1792.  
  1793. WDJ SDK Annotation #88
  1794. TYPE:       Win3.1
  1795. TOPIC:      List box messages 
  1796. KEYWORD:    List box messages 
  1797.  
  1798. Internally, listboxes maintain two 32-bit DWORDs for each
  1799. listbox item.  The first DWORD points to the text for the item
  1800. and the second DWORD contains whatever custom data you would
  1801. like; you can get it via LB_GETITEMDATA or set it via
  1802. LB_SETITEMDATA.  Some messages refer to one or the other of
  1803. these DWORDs, depending on whether the LBS_HASSTRINGS style is
  1804. set:
  1805.  
  1806. Message             LBS_HASSTRINGS?   Refers to:^
  1807. ==========================================================^
  1808. LB_ADDSTRING        Yes             text pointer (lParam)^
  1809. LB_ADDSTRING        No              custom data  (lParam)^
  1810. LB_INSERTSTRING     Yes             text pointer (lParam)^
  1811. LB_INSERTSTRING     No              custom data  (lParam)^
  1812. LB_GETTEXT          Yes             returns text pointer^
  1813. LB_GETTEXT          No              returns custom data^
  1814. LB_GETITEMDATA      either          returns custom data^
  1815. LB_SETITEMDATA      either          sets custom data (lParam)^
  1816. WM_DRAWITEM         either          custom data (in itemData field)^
  1817.  
  1818. In other words, if LBS_HASSTRINGS is not set, you cannot access
  1819. the normal text pointer -- all messages operate on the custom
  1820. data.  But if LBS_HASSTRINGS is set, you can access both the
  1821. normal text as well as the extra DWORD of custom data. 
  1822.  
  1823. Submitted by V. Ramachandran
  1824.  
  1825.  
  1826. ------------------------------------------------------------
  1827.  
  1828. WDJ SDK Annotation #89
  1829. TYPE:       Win3.1
  1830. TOPIC:      SetTimer (2.x)
  1831. KEYWORD:    SetTimer
  1832.  
  1833. Though the documentation does not mention this, you can
  1834. change the timer interval after you create the timer.  If
  1835. you call SetTimer() with a window handle and a timer ID
  1836. equal to an existing timer and specify a different time
  1837. interval, SetTimer() updates the timer to the new time
  1838. interval. 
  1839.  
  1840. Example:
  1841.  
  1842. Use the following line to set a timer to a particular time
  1843. interval. 
  1844.  
  1845. UINT nTimerID = SetTimer (hWnd, TIMER_ID, TIME_INTERVAL, NULL)
  1846.  
  1847. Calling the following line will reset the timer to twice the
  1848. time interval. 
  1849.  
  1850. nTimerID = SetTimer (hWnd, TIMER_ID, 2*TIME_INTERVAL, NULL)
  1851.  
  1852. Submitted by V. Ramachandran.
  1853.  
  1854.  
  1855. ------------------------------------------------------------
  1856.  
  1857. WDJ SDK Annotation #90
  1858. TYPE:       Win3.1
  1859. TOPIC:      TranslateAccelerator (2.x)
  1860. KEYWORD:    TranslateAccelerator
  1861.  
  1862. Contrary to the documentation, both WM_INITMENU and
  1863. WM_INITMENUPOPUP get sent, even if the menu item is disabled,
  1864. and even if the window is minimized and the keystroke matches no
  1865. menu items. 
  1866.  
  1867. Submitted by V. Ramachandran.
  1868.  
  1869.  
  1870. ------------------------------------------------------------
  1871.  
  1872. WDJ SDK Annotation #91
  1873. TYPE:       Win3.1
  1874. TOPIC:      GetPrivateProfileInt (3.0)
  1875. KEYWORD:    GetPrivateProfileInt
  1876.  
  1877. The documentation says you must use a positive integer
  1878. in the range 0 through 32,767 (0x7FFF) for the third
  1879. argument, which is the default value the function returns
  1880. if it cannot locate the desired entry in the .ini file.
  1881. In fact, you can pass any legal integer value for this
  1882. parameter -- it's just that since the function's return
  1883. type is defined to be UINT, you must cast the result to
  1884. int if you want to treat the result as a negative number.
  1885. For example, the following code works correctly, despite
  1886. what the documentation says:
  1887.  
  1888.  int Val = (int)GetPrivateProfileInt(
  1889.      "MyLib", "Debug", -1, "MyLib.ini");
  1890.  if(Val == -1)
  1891.      /* then no such entry found */
  1892.  
  1893.  
  1894. ------------------------------------------------------------
  1895.  
  1896. WDJ SDK Annotation #92
  1897. TYPE:       Win32
  1898. TOPIC:      WM_NOTIFY
  1899. KEYWORD:    WM_NOTIFY AND QuickInfo
  1900.  
  1901. If your dialog procedure handles a WM_NOTIFY that requires a
  1902. return value, note that you MUST both return a non-zero
  1903. value (to indicate to the dialog manager that you wish to
  1904. specify a return value for the message) AND store the
  1905. desired return value for the message in the window field
  1906. DWL_MSGRESULT.  The standard Windows header file windowsx.h
  1907. provides a macro called SetDlgMsgResult() that makes this
  1908. easy:
  1909.  
  1910.  #include <windowsx.h>
  1911.  //...
  1912.  case WM_NOTIFY  :
  1913.      {
  1914.      NMHDR* Head = (NMHDR*)lParam;
  1915.      if(Head->code == LVN_ENDLABELEDIT)
  1916.          // allow user to edit listview labels
  1917.          return SetDlgMsgResult(Dialog, WM_NOTIFY, TRUE);
  1918.      }
  1919.  
  1920.  
  1921. ------------------------------------------------------------
  1922.  
  1923. WDJ SDK Annotation #92
  1924. TYPE:       Win32
  1925. TOPIC:      LVN_ENDLABELEDIT
  1926. KEYWORD:    LVN_ENDLABELEDIT AND QuickInfo
  1927.  
  1928. If your dialog procedure handles a WM_NOTIFY that requires a
  1929. return value (as this one does), note that you MUST both
  1930. return a non-zero value (to indicate to the dialog manager
  1931. that you wish to specify a return value for the message) AND
  1932. store the desired return value for the message in the window
  1933. field DWL_MSGRESULT.  The standard Windows header file
  1934. windowsx.h provides a macro called SetDlgMsgResult() that
  1935. makes this easy:
  1936.  
  1937.  #include <windowsx.h>
  1938.  //...
  1939.  case WM_NOTIFY  :
  1940.      {
  1941.      NMHDR* Head = (NMHDR*)lParam;
  1942.      if(Head->code == LVN_ENDLABELEDIT)
  1943.          // allow user to edit listview labels
  1944.          return SetDlgMsgResult(Dialog, WM_NOTIFY, TRUE);
  1945.      }
  1946.  
  1947.  
  1948. ------------------------------------------------------------
  1949.  
  1950. WDJ SDK Annotation #92
  1951. TYPE:       Win32
  1952. TOPIC:      LVN_BEGINLABELEDIT
  1953. KEYWORD:    LVN_BEGINLABELEDIT AND QuickInfo
  1954.  
  1955. If your dialog procedure handles a WM_NOTIFY that requires a
  1956. return value (as this one does), note that you MUST both
  1957. return a non-zero value (to indicate to the dialog manager
  1958. that you wish to specify a return value for the message) AND
  1959. store the desired return value for the message in the window
  1960. field DWL_MSGRESULT.  The standard Windows header file
  1961. windowsx.h provides a macro called SetDlgMsgResult() that
  1962. makes this easy:
  1963.  
  1964.  #include <windowsx.h>
  1965.  //...
  1966.  case WM_NOTIFY  :
  1967.      {
  1968.      NMHDR* Head = (NMHDR*)lParam;
  1969.      if(Head->code == LVN_BEGINLABELEDIT)
  1970.          // allow user to edit listview labels
  1971.          return SetDlgMsgResult(Dialog, WM_NOTIFY, FALSE);
  1972.      }
  1973.  
  1974.  
  1975. ------------------------------------------------------------
  1976.  
  1977. WDJ SDK Annotation #93
  1978. TYPE:       Win3.1
  1979. TOPIC:      GetWindowText
  1980. KEYWORD:    GetWindowText AND QuickInfo
  1981.  
  1982. GetWindowText() and GetDlgItemText() will not work when
  1983. applied to a standard edit control that belongs to another
  1984. application.  The problem is that GetWindowText() and
  1985. GetDlgItemText() attempt to optimize by directly examining
  1986. the window caption of the target window.  An edit control
  1987. stores an empty string in its caption, not the edit control
  1988. text, so this fails.  You can avoid this bug by sending a
  1989. WM_GETTEXT explicitly:
  1990.  
  1991.  HWND OtherEdit;
  1992.  char Buffer[256];
  1993.  SendMessage(OtherEdit, WM_GETTEXT,
  1994.      sizeof(Buffer), (LPARAM)Buffer);
  1995.  
  1996.  
  1997.  
  1998. ------------------------------------------------------------
  1999.  
  2000. WDJ SDK Annotation #93
  2001. TYPE:       Win3.1
  2002. TOPIC:      GetDlgItemText
  2003. KEYWORD:    GetDlgItemText AND QuickInfo
  2004.  
  2005. GetWindowText() and GetDlgItemText() will not work when
  2006. applied to a standard edit control that belongs to another
  2007. application.  The problem is that GetWindowText() and
  2008. GetDlgItemText() attempt to optimize by directly examining
  2009. the window caption of the target window.  An edit control
  2010. stores an empty string in its caption, not the edit control
  2011. text, so this fails.  You can avoid this bug by sending a
  2012. WM_GETTEXT explicitly:
  2013.  
  2014.  HWND OtherEdit;
  2015.  char Buffer[256];
  2016.  SendMessage(OtherEdit, WM_GETTEXT,
  2017.      sizeof(Buffer), (LPARAM)Buffer);
  2018.  
  2019.  
  2020. ------------------------------------------------------------
  2021.  
  2022. WDJ SDK Annotation #94
  2023. TYPE:       Win32
  2024. TOPIC:      LVM_GETCOLUMNWIDTH
  2025. KEYWORD:    LVM_GETCOLUMNWIDTH AND QuickInfo
  2026.  
  2027. The documentation claims that this message returns the
  2028. column width if successful, "or zero otherwise".  In fact,
  2029. if you specify an invalid column number, this function
  2030. returns garbage.  Therefore, you cannot use this message to
  2031. count the number of columns in a listview control.  The
  2032. associated message, LVM_GETCOLUMN, does correctly return
  2033. zero when passed an invalid column number, so you can use
  2034. LVM_GETCOLUMN to determine the number of columns in a
  2035. listview control. 
  2036.  
  2037. ------------------------------------------------------------
  2038.  
  2039. WDJ SDK Annotation #95
  2040. TYPE:       Win3.1
  2041. TOPIC:      SystemParametersInfo (3.1)
  2042. KEYWORD:    SystemParametersInfo AND QuickInfo
  2043.  
  2044. The documentation says that the screen saver time out
  2045. (SPI_GETSCREENSAVETIMEOUT) is specified in milliseconds.  In
  2046. fact, the value returned is in seconds.
  2047.  
  2048. Submitted by: Carlton Guc
  2049.  
  2050.  
  2051.  
  2052. ------------------------------------------------------------
  2053.  
  2054. WDJ SDK Annotation #96
  2055. TYPE:       Win32
  2056. TOPIC:      LVN_ENDLABELEDIT
  2057. KEYWORD:    LVN_ENDLABELEDIT AND QuickInfo
  2058.  
  2059. The documentation claims that there is no return value for
  2060. this message.  In fact, you should return FALSE if you want
  2061. to reject the user's editing, or TRUE if you want to allow
  2062. the changes to the listview item.  If you are handling this
  2063. notification inside a dialog procedure, remember that you
  2064. must return a non-zero result AND store the message result
  2065. (either TRUE or FALSE) in DWL_MSGRESULT, using either
  2066. SetWindowLong() or the SetDlgMsgResult() macro (defined in
  2067. windowsx.h). 
  2068.  
  2069. Submitted by: Poul A. Costinsky
  2070.  
  2071.  
  2072. ------------------------------------------------------------
  2073.  
  2074. WDJ SDK Annotation #98
  2075. TYPE:       Win32
  2076. TOPIC:      RegSetValueEx
  2077. KEYWORD:    RegSetValueEx AND QuickInfo
  2078.  
  2079. For string-based data types, such as REG_SZ, this function
  2080. behaves differently under Win95 and NT.  Under Win95, if you
  2081. pass a value of "abcd" and a length of 4, the function will
  2082. actually append a null byte, and if you retrieve the value
  2083. later, you will find it has a length of 5.  Under NT, this
  2084. function stores exactly what you tell it to store. 
  2085.  
  2086. Submitted by Paula Tomlinson.
  2087.  
  2088. ------------------------------------------------------------
  2089.  
  2090. WDJ SDK Annotation #97
  2091. TYPE:       Win32
  2092. TOPIC:      LVN_ITEMCHANGING
  2093. KEYWORD:    LVN_ITEMCHANGING AND QuickInfo
  2094.  
  2095. The documentation incorrectly claims that you have to return
  2096. TRUE to allow the change, or FALSE to prevent it.  In fact,
  2097. you have to return FALSE to allow the change or TRUE to
  2098. prevent it. 
  2099.  
  2100. Submitted by V. Ramachandran.
  2101.  
  2102.  
  2103.  
  2104. ------------------------------------------------------------
  2105.  
  2106. WDJ SDK Annotation #99
  2107. TYPE:       Win32
  2108. TOPIC:      LV_DISPINFO
  2109. KEYWORD:    LV_DISPINFO AND QuickInfo
  2110.  
  2111. The documentation says you can set the LVIF_DI_SETITEM flag
  2112. in the mask member to have Windows store the string and not
  2113. ask for it again.  It fails to point out that this only
  2114. works for subitem 0 (the first column), so you would still
  2115. have to handle requests for the text of the other columns. 
  2116.  
  2117. Submitted by V. Ramachandran.
  2118.  
  2119.  
  2120. ------------------------------------------------------------
  2121.  
  2122. WDJ SDK Annotation #100
  2123. TYPE:       Win32
  2124. TOPIC:      LVM_EDITLABEL
  2125. KEYWORD:    LVM_EDITLABEL AND QuickInfo
  2126.  
  2127. Note that the listview control implements in-place editing
  2128. by creating an edit control on the fly.  Unfortunately, it
  2129. assigns that edit control a child ID of IDOK, which means
  2130. that the parent of the listview control will receive edit
  2131. control notifications that it might not expect.  For
  2132. example, if your listview control is in a dialog box, and
  2133. your dialog procedure contains code like this:
  2134.  
  2135.  // inside WM_COMMAND handler...
  2136.  if(ControlId == IDOK)
  2137.      EndDialog(Dialog, TRUE);
  2138.  
  2139. Then it may terminate the dialog when the user starts
  2140. editing a listview item (since the transient edit control
  2141. will send notifications like EN_CHANGE, with a control ID of
  2142. IDOK). The above code should read:
  2143.  
  2144.  // inside WM_COMMAND handler...
  2145.  if(ControlId == IDOK && NotifyCode == BN_CLICKED)
  2146.      EndDialog(Dialog, TRUE);
  2147.  
  2148. to be safe.
  2149.  
  2150.  
  2151.  
  2152.  
  2153.  
  2154.  
  2155. ------------------------------------------------------------
  2156.  
  2157. WDJ SDK Annotation #101
  2158. TYPE:       Win3.1
  2159. TOPIC:      GetWindowTextLength (2.x)
  2160. KEYWORD:    GetWindowTextLength AND QuickInfo
  2161.  
  2162. Due to a bug in Windows 3.1, both GetWindowTextLength() and
  2163. WM_GETTEXTLENGTH return -1 if you use it on a combobox of
  2164. style CBS_DROPDOWNLIST. 
  2165.  
  2166. Submitted by Mircea Neacsu
  2167.  
  2168.  
  2169.  
  2170. ------------------------------------------------------------
  2171.  
  2172. WDJ SDK Annotation #102
  2173. TYPE:       Win32
  2174. TOPIC:      LB_ADDSTRING
  2175. KEYWORD:    LB_ADDSTRING AND QuickInfo
  2176.  
  2177. If you are planning to add a large number (more than 100) of
  2178. strings by calling LB_ADDSTRING, LB_INSERTSTRING, LB_DIR, or
  2179. LB_ADDFILE, consider first sending the new Win32 message
  2180. LB_INITSTORAGE to give the listbox a chance to preallocate
  2181. memory, thus speeding up the process. 
  2182.  
  2183. Submitted by V. Ramachandran.
  2184.  
  2185.  
  2186. ------------------------------------------------------------
  2187.  
  2188. WDJ SDK Annotation #102
  2189. TYPE:       Win32
  2190. TOPIC:      LB_ADDSTRING
  2191. KEYWORD:    LB_ADDSTRING AND QuickInfo
  2192.  
  2193. If you are planning to add a large number (more than 100) of
  2194. strings by calling LB_ADDSTRING, LB_INSERTSTRING, LB_DIR, or
  2195. LB_ADDFILE, consider first sending the new Win32 message
  2196. LB_INITSTORAGE to give the listbox a chance to preallocate
  2197. memory, thus speeding up the process. 
  2198.  
  2199. Submitted by V. Ramachandran.
  2200.  
  2201.  
  2202. ------------------------------------------------------------
  2203.  
  2204. WDJ SDK Annotation #103
  2205. TYPE:       Win32
  2206. TOPIC:      LoadString
  2207. KEYWORD:    LoadString AND QuickInfo
  2208.  
  2209. Even though resource strings are stored as Unicode for both
  2210. Win95 and NT programs, Win95 does not provide an
  2211. implementation of the Unicode version of LoadString()
  2212. (LoadStringW()).  This usually trips up NT programmers who
  2213. want to create a single .exe for both operating systems and
  2214. yet still use Unicode under NT.  In that case, you must at
  2215. runtime detect that you are running under Win95 and, in that
  2216. case, explicitly call LoadStringA().  Otherwise, if you have
  2217. compiled with _UNICODE defined, LoadString() will expand
  2218. into LoadStringW(), which is just a stub that fails under
  2219. Win95. 
  2220.  
  2221. Submitted by Paula Tomlinson.
  2222.  
  2223.  
  2224.  
  2225. ------------------------------------------------------------
  2226.  
  2227. WDJ SDK Annotation #104
  2228. TYPE:       Win32
  2229. TOPIC:      LVN_DELETEITEM
  2230. KEYWORD:    LVN_DELETEITEM AND QuickInfo
  2231.  
  2232. The documentation implies that this notification
  2233. arrives after the item is deleted. In fact, it
  2234. arrives before the item is deleted from the listview
  2235. control.
  2236.  
  2237. Submitted by V. Ramachandran.
  2238.  
  2239.  
  2240. ------------------------------------------------------------
  2241.  
  2242. WDJ SDK Annotation #105
  2243. TYPE:       Win32
  2244. TOPIC:      IsWindow
  2245. KEYWORD:    IsWindow AND QuickInfo
  2246.  
  2247. The documentation claims this function returns TRUE if the
  2248. given handle is a valid window handle.  That was true under
  2249. Windows 3.x and is true under Windows NT, but Windows 95
  2250. returns a large non-zero value that is not equal to 1 (nor
  2251. is it equal to the window handle). In an un-indexed help
  2252. topic in the initial Win95 SDK, Microsoft reveals that
  2253. Win95 functions with BOOL return types are only guaranteed
  2254. to return non-zero when the documentation claims they
  2255. return TRUE. Windows NT appears to behave as documented.
  2256.  
  2257. Submitted by: David Lowndes
  2258.  
  2259.  
  2260. ------------------------------------------------------------
  2261.  
  2262. WDJ SDK Annotation #105
  2263. TYPE:       Win32
  2264. TOPIC:      GetClientRect
  2265. KEYWORD:    GetClientRect AND QuickInfo
  2266.  
  2267. The documentation claims this function returns TRUE if the
  2268. given handle is a valid window handle.  That was true under
  2269. Windows 3.x and is true under Windows NT, but Windows 95
  2270. returns a large non-zero value that is not equal to 1 (nor
  2271. is it equal to the window handle). In an un-indexed help
  2272. topic in the initial Win95 SDK, Microsoft reveals that
  2273. Win95 functions with BOOL return types are only guaranteed
  2274. to return non-zero when the documentation claims they
  2275. return TRUE. Windows NT appears to behave as documented.
  2276.  
  2277. Submitted by: Ron Scott
  2278.  
  2279.  
  2280. ------------------------------------------------------------
  2281.  
  2282. WDJ SDK Annotation #106
  2283. TYPE:       Win32
  2284. TOPIC:      WM_GETDLGCODE
  2285. KEYWORD:    WM_GETDLGCODE AND QuickInfo
  2286.  
  2287. The documentation WM_GETDLGCODE states that this message has
  2288. no parameters. But the truth is that if the user presses a
  2289. key, lParam will contain a pointer to a MSG structure
  2290. containing information about the event that made Windows send
  2291. the WM_GETDLGCODE message.  This is indirectly documented in
  2292. windowsx.h, where the HANDLE_WM_GETDLGCODE() macro passes
  2293. two arguments to the handler: the window handle and (MSG
  2294. FAR*)(lParam). 
  2295.  
  2296. Submitted by: Patrick Tennberg
  2297. Reference: Microsoft Knowledge Base article Q83302
  2298.  
  2299.  
  2300.  
  2301. ------------------------------------------------------------
  2302.  
  2303. WDJ SDK Annotation #107
  2304. TYPE:       Win32
  2305. TOPIC:      DBT_DEVICEQUERYREMOVE
  2306. KEYWORD:    DBT_DEVICEQUERYREMOVE AND QuickInfo
  2307.  
  2308. The documentation incorrectly says that you should return
  2309. FALSE if you want to veto the device removal.  In fact, you
  2310. have to return BROADCAST_QUERY_DENY; returning FALSE will
  2311. allow the device removal to proceed. 
  2312.  
  2313. Submitted by Paula Tomlinson.
  2314.  
  2315.  
  2316. ------------------------------------------------------------
  2317.  
  2318. WDJ SDK Annotation #108
  2319. TYPE:       Win3.1
  2320. TOPIC:      LZOpenFile
  2321. KEYWORD:    LZOpenFile AND QuickInfo
  2322.  
  2323.  
  2324. However, if lpszFile contains only a filename and extension
  2325. (i.e.  no path is specified), then LZOpenFile() use the same
  2326. searching logic as OpenFile().  If no file with the matching
  2327. name (and extension) is found, then it searches for the
  2328. compressed filename.  The compressed file has a _ as the
  2329. last character (e.g., the compressed version of "readme.txt"
  2330. is "readme.tx_").  Therefore if you use LZOpenFile() to open
  2331. a file called "readme.txt", it searches as follows:
  2332.  
  2333.  1) it looks for "readme.txt" using the same search
  2334.     algorithm as OpenFile().
  2335.  2) if the file was not found, it uses the same
  2336.     algorithm to search for "readme.tx_".
  2337.  
  2338. That means LZOpenFile() might open a "readme.tx_" file from
  2339. a directory other than the one you expected.  Even if you
  2340. specify the complete filename (such as
  2341. "c:\demo\readme.txt"), LZOpenFile() first searches for the
  2342. specified file, and if the specified filename is not found,
  2343. it searches for the compressed file in the same directory
  2344. ("c:\demo\readme.tx_"). 
  2345.  
  2346. Submitted by V. Ramachandran.
  2347.  
  2348.  
  2349. ------------------------------------------------------------
  2350.  
  2351. WDJ SDK Annotation #109
  2352. TYPE:       Win32
  2353. TOPIC:      SetCapture
  2354. KEYWORD:    SetCapture AND QuickInfo
  2355.  
  2356. This help topic does not document the fact that when the
  2357. mouse is captured, menu hotkeys (for example, Alt+F for
  2358. accessing the File menu) and other keyboard accelerators do
  2359. not work (ex: Alt+F4).  This is because DefWindowProc()
  2360. handles the WM_SYSCHAR and WM_SYSCOMMAND messages
  2361. differently if the mouse has been captured (by any window). 
  2362.  
  2363. DefWindowProc() processes the WM_SYSCHAR message to check if
  2364. the pressed key is a menu hotkey (Alt+F for example).  If it
  2365. is, then it causes the menu to drop down.  However, if the
  2366. mouse is captured, it does not do the above action. 
  2367. Whenever DefWindowProc() sees a WM_SYSCOMMAND and finds that
  2368. the mouse is captured, then it does nothing. 
  2369.  
  2370. Submitted by V. Ramachandran.
  2371.  
  2372.  
  2373.  
  2374. ------------------------------------------------------------
  2375.  
  2376. WDJ SDK Annotation #110
  2377. TYPE:       Win32
  2378. TOPIC:      RegCreateKey
  2379. KEYWORD:    RegCreateKey AND QuickInfo
  2380.  
  2381. The documentation for RegCreateKey(), RegCreateKeyEx(),
  2382. RegOpenKey(), and RegOpenKeyEx() all list several predefined
  2383. handles you can use, such as HKEY_CURRENT_USER.  However,
  2384. they fail to document the predefined key
  2385. HKEY_CURRENT_CONFIG, which has a structure similar to the
  2386. registry tree under HKEY_LOCAL_MACHINE, but is for storing
  2387. information specific to the current hardware profile. 
  2388.  
  2389. Submitted by Paula Tomlinson.
  2390.  
  2391.  
  2392.  
  2393.  
  2394.  
  2395. ------------------------------------------------------------
  2396.  
  2397. WDJ SDK Annotation #111
  2398. TYPE:       Win32
  2399. TOPIC:      CreateFile
  2400. KEYWORD:    CreateFile AND QuickInfo
  2401.  
  2402. The documentation claims CreateFile() returns a handle that
  2403. can be used to access the object.  However, under both NT
  2404. and Win95, CreateFile() will appear to succeed and return a
  2405. valid handle if you attempt to open a file with
  2406. GENERIC_WRITE permissions on a read-only medium (e.g.,
  2407. protected floppy or CD-ROM).  If you then try to perform a
  2408. write with the returned handle, that will fail. 
  2409.  
  2410.  
  2411. Submitted by: David Lowndes
  2412.  
  2413.  
  2414.  
  2415.  
  2416. ------------------------------------------------------------
  2417.  
  2418. WDJ SDK Annotation #112
  2419. TYPE:       Win32
  2420. TOPIC:      GetWindowText
  2421. KEYWORD:    GetWindowText AND QuickInfo
  2422.  
  2423. The third argument is the "maximum numbers of characters to
  2424. copy".  It may not be clear that this number must include
  2425. the NULL byte so, for example, it never makes sense to set
  2426. this argument to 1 since all you could get back is a NULL
  2427. byte.  If you want to use GetWindowText() to retrieve a
  2428. single character (e.g., from an edit control), you would
  2429. have to specify a length of 2 -- one for the character and
  2430. one for the terminating NULL byte. 
  2431.  
  2432. Submitted by: Tony Yuricich
  2433.  
  2434.  
  2435.  
  2436.  
  2437. ------------------------------------------------------------
  2438.  
  2439. WDJ SDK Annotation #113
  2440. TYPE:       Win32
  2441. TOPIC:      keybd_event
  2442. KEYWORD:    keybd_event AND QuickInfo
  2443.  
  2444. You can use this function to toggle keys such as the Caps
  2445. Lock, Scroll Lock, and Num Lock.  Unfortunately, though
  2446. toggling these three keys works correctly under NT, you
  2447. cannot use this function to toggle the Num Lock key under
  2448. Win95. 
  2449.  
  2450.  
  2451.  
  2452. ------------------------------------------------------------
  2453.  
  2454. WDJ SDK Annotation #114
  2455. TYPE:       Win3.1
  2456. TOPIC:      WM_CTLCOLOR (2.x)
  2457. KEYWORD:    WM_CTLCOLOR AND QuickInfo
  2458.  
  2459.  
  2460.  
  2461. The documentation incorrectly states that "the return value
  2462. from this message has no effect on a button with the
  2463. BS_PUSHBUTTON or BS_DEFPUSHBUTTON style." In fact, returning
  2464. a brush handle in response to this message appears to
  2465. determine the color of the pushbutton window background,
  2466. which is visible as the tiny areas in the corners of the
  2467. pushbutton window.  Note that under Windows 95, pushbuttons
  2468. fill the entire client area of their windows, thus hiding
  2469. the window background from view. 
  2470.  
  2471. Submitted by: Forest Wilkinson
  2472.  
  2473.  
  2474.  
  2475.  
  2476. ------------------------------------------------------------
  2477.  
  2478.  
  2479.  
  2480. WDJ SDK Annotation #115
  2481. TYPE:       Win32
  2482. TOPIC:      GlobalDeleteAtom
  2483. KEYWORD:    GlobalDeleteAtom AND QuickInfo
  2484.  
  2485. The documentation for GlobalDeleteAtom states:
  2486.  
  2487.   "The only way to ensure that an atom has been deleted from the 
  2488. atom table is to call this function repeatedly until it fails."
  2489.  
  2490. Unfortunately, a 32-bit program running under Win NT 3.51 never fails,
  2491. making for an infinite loop (Windows 95 functions as documented).
  2492. Microsoft says this may be fixed in the next release (NT 4.0).
  2493.  
  2494. Submitted by Ken Brown
  2495.  
  2496.  
  2497. ------------------------------------------------------------
  2498.  
  2499. WDJ SDK Annotation #116
  2500. TYPE:       Win32
  2501. TOPIC:      LB_ADDSTRING
  2502. KEYWORD:    LB_ADDSTRING AND QuickInfo
  2503.  
  2504. If your listbox has the WS_HSCROLL style, and if you are
  2505. adding a string wider than the listbox, you may have to send
  2506. a LB_SETHORIZONTALEXTENT message to make the horizontal
  2507. scrollbar appear.  The listbox does not automatically check
  2508. each newly added string and add the horizontal scrollbar
  2509. when a too-wide string is added or inserted. 
  2510.  
  2511.  
  2512.  
  2513.  
  2514. ------------------------------------------------------------
  2515.  
  2516.  
  2517.  
  2518. WDJ SDK Annotation #117
  2519. TYPE:       Win32
  2520. TOPIC:      LB_DIR
  2521. KEYWORD:    LB_DIR AND QuickInfo
  2522.  
  2523. If you pass a long filename to LB_DIR, it works
  2524. under NT 3.51, but fails under Win95 because it
  2525. relies on the 16-bit listbox which was not changed
  2526. to handle long filenames. You can avoid the error
  2527. by first translating the filename to a short filename
  2528. by calling GetShortPathName(). The LB_DIR will not
  2529. fail, but it will still display only the short versions
  2530. of any long filenames in the subdirectory.
  2531.  
  2532. Reference: Microsoft Knowledge Base article Q131286
  2533.  
  2534.  
  2535.  
  2536.  
  2537. ------------------------------------------------------------
  2538.  
  2539.  
  2540.  
  2541. WDJ SDK Annotation #118
  2542. TYPE:       Win32
  2543. TOPIC:      ReadFile
  2544. KEYWORD:    ReadFile AND QuickInfo
  2545.  
  2546. The documentation correctly points out that Win95
  2547. does not support OVERLAPPED I/O. However, it incorrectly
  2548. states that you must pass a pointer to a structure of
  2549. type OVERLAPPED if the file was created (or opened)
  2550. with the flag FILE_FLAG_OVERLAPPED. In fact, if you
  2551. pass a pointer (rather than NULL) under Windows 95,
  2552. ReadFile() returns FALSE, and GetLastError() returns
  2553. ERROR_INVALID_PARAMETER, whether or not the file
  2554. was created/opened with the FILE_FLAG_OVERLAPPED
  2555. flag. That means that if you want to code a call
  2556. to ReadFile() that works correctly for both
  2557. synchronous and asynchronous I/O, you must detect
  2558. at runtime that you're running under Win95 and
  2559. treat that case differently.
  2560.  
  2561.  
  2562.  
  2563. -----------------------------------------------------------------------
  2564.  
  2565.  
  2566. WDJ SDK Annotation #119
  2567. TYPE:       Win32
  2568. TOPIC:      WinMain
  2569. KEYWORD:    WinMain AND QuickInfo
  2570.  
  2571. Note that the string passed in lpCmdLine is not the same as
  2572. the string returned by GetCommandLine().  The string in
  2573. lpCmdLine contains the command line arguments only, but
  2574. GetCommandLine() returns the program name followed by the
  2575. arguments. 
  2576.  
  2577. If you specify the following command: 'winword abc.doc', and
  2578. winword exists in d:\msoffice\winword.exe, lpCmdLine will
  2579. contain 'abc.doc', while GetCommandLine will return
  2580. '"d:\msoffice\winword.exe" abc.doc' Note the double quotes
  2581. around the exe name. 
  2582.  
  2583. Submitted by Phil Rodgers.
  2584.  
  2585. ----------------------------------------------------------------------
  2586.  
  2587.  
  2588. WDJ SDK Annotation #119
  2589. TYPE:       Win32
  2590. TOPIC:      GetCommandLine
  2591. KEYWORD:    GetCommandLine AND QuickInfo
  2592.  
  2593. Note that the string passed in the lpCmdLine parameter to
  2594. WinMain is not the same as the string returned by
  2595. GetCommandLine().  GetCommandLine() returns the complete
  2596. program name enclosed in double quotes, followed by the
  2597. arguments; whereas the lpCmdLine parameter of WinMain
  2598. contains the command line arguments only. 
  2599.  
  2600. If you specify the following command: 'winword abc.doc', and
  2601. winword exists in d:\msoffice\winword.exe, lpCmdLine will
  2602. contain 'abc.doc', while GetCommandLine will return
  2603. '"d:\msoffice\winword.exe" abc.doc' Note the double quotes
  2604. around the exe name. 
  2605.  
  2606. Submitted by Phil Rodgers.
  2607.  
  2608. ----------------------------------------------------------------------
  2609.  
  2610. WDJ SDK Annotation #120
  2611. TYPE:       Win32
  2612. TOPIC:      ShellAbout
  2613. KEYWORD:    ShellAbout AND QuickInfo
  2614.  
  2615. The documentation says that in Windows 95 ShellAbout will
  2616. prepend "Microsoft Windows" to the title of the application. 
  2617. This is not true.  Actually, this function prepends only
  2618. "Microsoft", so if your app is called "MyApp", the title
  2619. will read "Microsoft MyApp". 
  2620.  
  2621. Submitted by Luis A. Ramos.
  2622.  
  2623. ----------------------------------------------------------------------
  2624.  
  2625. WDJ MFC Annotation #121
  2626. TYPE:       MFC 4
  2627. TOPIC:      CPropertySheet::SetTitle
  2628. KEYWORD:    SetTitle AND QuickInfo
  2629.  
  2630. The parameters to this function are interchanged: it should
  2631. actually read:
  2632.  
  2633. void SetTitle (LPCTSTR lpszText, UINT nStyle);
  2634.  
  2635. Submitted by Margaret M. O'Connell.
  2636.  
  2637. ----------------------------------------------------------------------
  2638.  
  2639. WDJ MFC Annotation #122
  2640. TYPE:       MFC 1.5x
  2641. TOPIC:      CCmdTarget::GetIDispatch
  2642. KEYWORD:    GetIDispatch AND QuickInfo
  2643.  
  2644. The MFC 1.5x documentation incorrectly states that this
  2645. function takes no parameters. It should read:
  2646.  
  2647.  LPDISPATCH GetIDispatch (BOOL bAddRef)
  2648.  bAddRef - specifies whether to increment
  2649.            the reference count for the object.
  2650.  
  2651. This has been corrected in the MFC 4.0 documentation.
  2652.  
  2653. Submitted by V.Ramachandran.
  2654.  
  2655. ----------------------------------------------------------------------
  2656.  
  2657. WDJ SDK Annotation #123
  2658. TYPE:       Win16
  2659. TOPIC:      LB_SELECTSTRING
  2660. KEYWORD:    LB_SELECTSTRING
  2661.  
  2662. win31wh.hlp fails to mention that this message works only
  2663. with single select listboxes.  For multi-select listboxes it
  2664. returns LB_ERR. 
  2665.  
  2666. Submitted by Dino Esposito.
  2667.  
  2668. ----------------------------------------------------------------------
  2669.  
  2670.  
  2671.  
  2672. WDJ SDK Annotation #124
  2673. TYPE:       Win32
  2674. TOPIC:      AdjustWindowRect
  2675. KEYWORD:    AdjustWindowRect AND QuickInfo
  2676.  
  2677. The documentation for AdjustWindowRect() and
  2678. AdjustWindowRectEx() has a number of problems. 
  2679.  
  2680. 1.  Though the documentation says that window titles and
  2681. borders are not taken into account, they function does
  2682. account for these styles. 
  2683.  
  2684. 2.  Add 1 to the rect.bottom returned by this function. 
  2685. There is a one-off error in the y direction. 
  2686.  
  2687. 3.  The meaning of the rect parameter is not well explained. 
  2688. The input to AdjustWindowRectEx is the window coordinates of
  2689. the top-left and bottom-right corners of the desired client
  2690. area.  AdjustWindowRectEx inflates the specified rectangle
  2691. to include the caption, border and other non-client objects
  2692. specified by the style parameter. 
  2693.  
  2694.  
  2695. Reference: MSDN Dr.GUI #10 - Calculated Client Window Size.
  2696.  
  2697. Submitted by Etay Szekely.
  2698.  
  2699. ----------------------------------------------------------------------
  2700.  
  2701.  
  2702. WDJ SDK Annotation #124
  2703. TYPE:       Win32
  2704. TOPIC:      AdjustWindowRectEx
  2705. KEYWORD:    AdjustWindowRectEx AND QuickInfo
  2706.  
  2707. The documentation for AdjustWindowRect() and
  2708. AdjustWindowRectEx() has a number of problems. 
  2709.  
  2710. 1.  Though the documentation says that window titles and
  2711. borders are not taken into account, they function does
  2712. account for these styles. 
  2713.  
  2714. 2.  Add 1 to the rect.bottom returned by this function. 
  2715. There is a one-off error in the y direction. 
  2716.  
  2717. 3.  The meaning of the rect parameter is not well explained. 
  2718. The input to AdjustWindowRectEx is the window coordinates of
  2719. the top-left and bottom-right corners of the desired client
  2720. area.  AdjustWindowRectEx inflates the specified rectangle
  2721. to include the caption, border and other non-client objects
  2722. specified by the style parameter. 
  2723.  
  2724.  
  2725. Reference: MSDN Dr.GUI #10 - Calculated Client Window Size.
  2726.  
  2727. Submitted by Etay Szekely.
  2728.  
  2729.  
  2730. ----------------------------------------------------------------------
  2731.  
  2732. WDJ MFC Annotation #125
  2733. TYPE:       MFC 3.1 and 3.2
  2734. TOPIC:      CImageList::DeleteObject
  2735. KEYWORD:    DeleteObject AND QuickInfo
  2736.  
  2737. VC++ 2.1 and 2.2 help files incorrectly documented this
  2738. function to delete image lists, while it actually never
  2739. existed.  The correct function to delete an image list is
  2740. CImageList::DeleteImageList(); it returns non-zero if
  2741. successful and zero if it fails.
  2742.  
  2743. This error is corrected in the VC++ 4.0 documentation.
  2744.  
  2745. Submitted by Barry Tannenbaum.
  2746.  
  2747. ----------------------------------------------------------------------
  2748.  
  2749. WDJ SDK Annotation #126
  2750. TYPE:       Win32
  2751. TOPIC:      AVIFileOpen
  2752. KEYWORD:    AVIFileOpen
  2753.  
  2754. The documentation specifies that using the OF_CREATE flag
  2755. will cause an existing file to be truncated to zero length. 
  2756. In reality, it has no effect: the file length remains the
  2757. same, and the old data is intact once the file is closed. 
  2758.  
  2759. Submitted by Tim Lesher.
  2760.  
  2761. ----------------------------------------------------------------------
  2762.  
  2763. WDJ SDK Annotation #127
  2764. TYPE:       Win16
  2765. TOPIC:      CBTProc
  2766. KEYWORD:    CBTProc
  2767.  
  2768. The CBTProc documentation fails to mention that you can
  2769. return 0 to allow the operation and 1 to prevent it for
  2770. HCBT_SETFOCUS notification also.  The documentation has been
  2771. corrected in the Win32 help file. 
  2772.  
  2773. Submitted by V.Ramachandran.
  2774.  
  2775. ----------------------------------------------------------------------
  2776.  
  2777. WDJ SDK Annotation #128
  2778. TYPE:       Win32
  2779. TOPIC:      GetDialogBaseUnits
  2780. KEYWORD:    GetDialogBaseUnits AND QuickInfo
  2781.  
  2782. GetDialogBaseUnits() does not return correct dialog base
  2783. units if the dialog is not using the system font.  Use the
  2784. following function instead:
  2785.  
  2786.  DWORD WDJ_GetDialogBaseUnits (HWND Dialog)
  2787.  {
  2788.     int BaseX, BaseY;
  2789.     RECT R;
  2790.     SetRect (&R, 0, 0, 4, 8);
  2791.     MapDialogRect (Dialog, &R);
  2792.     BaseX = R.right;
  2793.     BaseY = R.bottom;
  2794.     return (DWORD)MAKELONG (BaseX, BaseY);
  2795.  }
  2796.  
  2797. Reference: p54, January 1996 Windows Developer's Journal.
  2798.  
  2799.